How to change rotation in KeyAttribute in MotionLayout programatically - android-animation

I need to change rotation from 30 to -30 degrees while motion scene repeating. How to do this programatically?
R.xml.scene_01:
<MotionScene
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:motion="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Transition
motion:constraintSetStart="#id/start"
motion:constraintSetEnd="#id/end"
motion:duration="2000">
<KeyFrameSet>
<KeyAttribute
android:rotation="30"
motion:target="#id/button"
android:scaleX="1.3"
android:scaleY="1.3"
motion:framePosition="50"/>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="#+id/start">
<Constraint
android:id="#id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="#drawable/tut_ali_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="#+id/end">
<Constraint
android:id="#id/button"
android:layout_width="64dp"
android:layout_height="64dp"
android:src="#drawable/tut_ali_icon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</ConstraintSet>
</MotionScene>
Listener in MotionLayout:
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMotionLayout.setTransitionListener(new MotionLayout.TransitionListener() {
#Override
public void onTransitionChange(MotionLayout motionLayout, int i, int i1, float v) {
}
#Override
public void onTransitionCompleted(MotionLayout motionLayout, int currentId) {
if(currentId == R.id.end){
motionLayout.loadLayoutDescription(R.xml.scene_02);
motionLayout.transitionToStart();
}else{
motionLayout.loadLayoutDescription(R.xml.scene_01);
motionLayout.transitionToEnd();
}
}
});
mMotionLayout.transitionToEnd();
}
I need to change rotation in onTransitionCompleted method. As an option maybe can I create KeyFrameSet which using various KeyAttribute?
In R.xml.scene_02 I change only android:rotation="-30" but it seems loadLayoutDescription method doesn't work.
Such a movement as in the picture I want to get:
enter image description here

Not enough rep to comment, but why do you have 2 separate transitions specified?
Trying to understand the question, if you want it to consistently rotate with that listener, the following should work:
<Transition
motion:constraintSetEnd="#id/end"
motion:constraintSetStart="#id/start"
motion:duration="2000">
<KeyFrameSet>
<KeyAttribute
android:rotation="-45"
android:scaleX="2"
android:scaleY="2"
motion:framePosition="0"
motion:target="#id/button" />
<KeyAttribute
android:rotation="45"
android:scaleX="2"
android:scaleY="2"
motion:framePosition="50"
motion:target="#id/button" />
<KeyAttribute
android:rotation="-45"
android:scaleX="2"
android:scaleY="2"
motion:framePosition="100"
motion:target="#id/button" />
</KeyFrameSet>
</Transition>
This will have the button start and end at -45 degrees rotation and, halfway through the transition, will rotate to 45 degrees. Note that these are just value animations so they will NOT be applied to the object when it reaches the start or end - you'll need to specify the rotation in the start/end ConstraintSet attributes.

Related

RecyclerView nested in LinearLayout as well as Scrollview not scrolling to specific recycler item position

My code below doesnt work for each specific scrollto or smoothScrollTo, can anyone help me?
I basically want to be able to dynamically scroll to a specific Item position in the activity, e.g. if a specific recyclerviewItem has been clicked on it will go to the activity and scroll to the specific item. The position variable has been ranging from "recyclerview.getChildAdapterPosition(itemview)" to itemview.Bottom which also doesn't work.
Help would be appreciated.
private fun focusOnView(scroll: ScrollView, itemView : View?,position :Int) {
scroll.post(Runnable {
if (editBox != null) {
val x= 1
// scroll.scrollTo(0,NestedScrollView.FOCUS_DOWN)
// scroll.smoothScrollTo(0, scroll.bottom)
scroll.smoothScrollTo(0,position)
//scroll.fullScroll(130)
}
})
}
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/scrollView"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/contentreyclerpager"
android:layout_width="match_parent"
android:paddingTop="10dp"
android:layout_height="wrap_content" />
</RelativeLayout>
</ScrollView>
Why you use the nestedScollView smoothScrollTo with the position you have to give x,y coordonate i think in your case you can use recycleView.smoothScrollToPosition(yourPosition);

How can i use DataBinding for TextView?

i have a problem, i dont know how to use DataBinding for TextView. i made a DataBinding for Glide and it success, but for TextView i dont know how to do it
this is the code
viewModel2.shouldShowImageProfile.observe(this) {
Glide.with(binding.root)
.load(it)
.circleCrop()
.into(binding.rivProfile)
}
viewModel2.shouldShowUsername.observe(this){
TextView.with(binding.root) <- the TextView
.load(it)
.into(binding.tvHello)
}
I wrote my answer making an assumption about shouldShowUsername, but as that's your String value, you can do something like this:
viewModel2.shouldShowUsername.observe(this) { shouldShowUsername ->
binding.tvHello.isVisible = !shouldShowUsername.isNullOrEmpty()
binding.tvHello.text = shouldShowUsername
}
That'll cause your TextView to only be displayed when shouldShowUsername has a proper value then take that value and assign it to the TextView. If you want the TextView to always show up, you can skip that first line within the block.
If you dont want to use observe method on variables of viewmodel you can use data binding and change value of textview from the xml directly, so that you dont have to manually write binding.tvUserName.text = it.value. Below code shows example for usuage of data binding with xml and viewmodel.
XML:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.example.kotlinbasics.android_architecture.mvvm_architecture.ChatViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_red_light"
tools:context=".android_architecture.mvvm_architecture.UserOneFragment">
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/etMessageToSecond"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/_10sdp"
android:background="#drawable/text_field_background"
android:gravity="center"
android:hint="#string/enter_message"
android:padding="#dimen/_7sdp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.7" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/tvCurrentMessage"
android:text="#{`Current Message: `+viewModel.latestMessageFromFirst}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/_50sdp"
android:padding="#dimen/_10sdp"
android:textColor="#color/white"
android:textSize="#dimen/_20ssp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/etMessageToSecond" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
In the above example I am printing the live text in textview which user writes in the edittext field. Whenever user writes in edittext, its value gets updated in the viewmodel and textview access that value on runtime.
For image thing, you can do like, you can create custom binding adapter which updates the image. Example:
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivEmailVerification"
loadImageFromUrl="#{viewModel.emailVerifyImageUrl}"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tvIsEmailValid"
app:layout_constraintWidth_percent="0.7" />
and on BindingAdpater
#BindingAdapter("loadImageFromUrl")
fun ImageView.loadImageFromUrl(imageUrl: String) {
Picasso.get().load(imageUrl).into(this)
}

Start activity from button.setOnClickListener which lies in my RecyclerView

I want an activity/class to run on a Button click. The Button is inside my RecyclerView. I first had the code in my MainActivity with:
btnComplete.setOnClickListener {
startActivity(Intent(this#MainActivity, DelComplete::class.java))}
This code was in my onCreate of my MainActivity. How ever on running the code I found the error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
My first thought was that it could not reach the Button since it was in the RecyclerView. So I tried to put the code in my RecyclerView. But I read that it is not a good idea to put it in you RecyclerView and I dont know what to do with the Context as it keeps throwing errors.
RecyclerView:
txtbutton1.setOnClickListener {
confirmdel()
modal.tvdone = "Delivered"
Log.e("Clicked", "Successful delivery")
//this is where I add code to export data through api
modal.state = DataState.Success
Status = 1
notifyDataSetChanged()}
private fun confirmdel() {
startActivity(Intent(this, DelComplete::class.java))}
It might be as simple as filling in the Context but I am unsure what the Context must be to test that theory.
Recyclerview- table_list_item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/txtWOrder"
android:layout_width="160dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_content_cell_bg"
android:text="#string/worder"
android:textSize="18sp"
tools:ignore="TextContrastCheck" />
<TextView
android:id="#+id/txtDElNote"
android:layout_width="190dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_content_cell_bg"
android:text="#string/delnote"
android:textSize="18sp"
tools:ignore="TextContrastCheck" />
<TextView
android:id="#+id/txtCompany"
android:layout_width="190dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_content_cell_bg"
android:text="#string/company"
android:textSize="18sp"
tools:ignore="TextContrastCheck" />
<Button
android:id="#+id/btnComplete"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_header_cell_bg"
android:drawableTint="#70D5C8"
android:text="#string/button1"
android:textSize="18sp" />
<Button
android:id="#+id/btnException"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_content_cell_bg"
android:text="#string/button2"
android:textSize="18sp" />
<TextView
android:id="#+id/txttvdone"
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#drawable/table_content_cell_bg"
android:foregroundGravity="center_horizontal"
android:text=""
android:textAlignment="center"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="#+id/txtWeight"
android:layout_width="190dp"
android:layout_height="match_parent"
android:layout_gravity="top"
android:background="#drawable/table_content_cell_bg"
android:text="#string/weight"
android:textSize="18sp"
tools:ignore="TextContrastCheck" />
</LinearLayout>
The reason why I have a Button in my RecyclerView is on every entry a driver should be able to give feedback on a delivery. Every entry is a different order. Did I go the wrong way of doing this?
My Button does the following:
txtbutton1.setOnClickListener {
confirmdel()
modal.tvdone = "Delivered"
Log.e("Clicked", "Successful delivery")
//this is where I add code to export data through api
modal.state = DataState.Success
Status = 1
notifyDataSetChanged()
}
It does that with no problem. Now however I want to add an AlertDialog and update data in my DB with the setOnClickListener. Will this be possible from within my adapter?
You can use the context like this :
class Adapter(private val context: Context, private val myList: List<String>) :
RecyclerView.Adapter<Adapter.ViewHolder>()
And pass the context where required like this
private fun confirmdel() {
startActivity(Intent(context, DelComplete::class.java))}
You shouldn't put a button inside of your RecyclerView, unless you are referring to a button as the item itself.
RecyclerViews are used to render as much as items as you have in your data source, instead of hardcoding them, so I think you want to handle the click on a single item and navigate to another Activity with the data of that item.
You can do that by following these steps. This is a codelab made by Google and explains how to handle the item click.
In addition, you should do those too, in order to better understanding.RecyclerViews

How to implement scrolling in RecyclerView on Android TV?

I have an application which I need adapt for Android TV. This application contains horizontal RecyclerView and it doesn't scroll when I press D-pad buttons on remote control.
I found this solution, but it crashes.
Here is the code:
<ru.myapp.package.HorizontalPersistentFocusWrapper
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="#null"
android:scrollbars="none"/>
</ru.myapp.package.HorizontalPersistentFocusWrapper>
HorizontalPersistentFocusWrapper is the same as PersistentFocusWrapper but mPersistFocusVertical = false;
Crash occure in this place:
#Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
view = (View) view.getParent(); <<<------ Crash here
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG) Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}
Crash stacktrace:
java.lang.ClassCastException: android.view.ViewRootImpl cannot be cast to android.view.View
at ru.myapp.package.HorizontalPersistentFocusWrapper.requestChildFocus(HorizontalPersistentFocusWrapper.java:108)
at android.view.View.handleFocusGainInternal(View.java:5465)
at android.view.ViewGroup.handleFocusGainInternal(ViewGroup.java:714)
at android.view.View.requestFocusNoSearch(View.java:8470)
at android.view.View.requestFocus(View.java:8449)
at android.view.ViewGroup.requestFocus(ViewGroup.java:2747)
at android.view.View.requestFocus(View.java:8416)
at android.support.v4.widget.NestedScrollView.arrowScroll(NestedScrollView.java:1222)
at android.support.v4.widget.NestedScrollView.executeKeyEvent(NestedScrollView.java:551)
at android.support.v4.widget.NestedScrollView.dispatchKeyEvent(NestedScrollView.java:512)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
Use the lastest version of RecyclerView.
Or use at least
com.android.support:recyclerview-v7:23.2.0
See this link for more info:
https://code.google.com/p/android/issues/detail?id=190526&thanks=190526&ts=1445108573
Now for the important part:
New versions of RecyclerView started to obey the rules of its children (like height and width).
You must set your root view in child item XML to:
android:focusable="true"
Now, scrolling will go like it was intended.
Set the focusable to true in the root view of the recyclerview item. android:focusable="true" and apply a selector background to the root view item. Everything can be done in the xml files. With the following settings, the dpad or remote controller will be able to scroll up and down the list, the current selected item in the list will be highlighted.
The layout file for the root view of the list item in the RecyclerView: list_item.xml , the important parts here are android:background="#drawable/item_selector" and android:focusable="true"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/item_selector"
android:focusable="true">
<TextView
android:id="#+id/topic"
android:layout_width="match_parent"
android:layout_height="60dp"
android:textColor="#ffffff"
android:gravity="center"
tools:text="Education"/>
</LinearLayout>
The drawable selector file in the drawable folder: item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#000000" android:state_pressed="true"/>
<item android:drawable="#000000" android:state_selected="true"/>
<item android:drawable="#000000" android:state_focused="true"/>
<item android:drawable="#03A9F4"></item>
</selector>
The layout file containing the RecyclerView: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</android.support.constraint.ConstraintLayout>
Try this. Works for me.
#Override
public void requestChildFocus(View child, View focused) {
super.requestChildFocus(child, focused);
View view = focused;
while (view != null && view.getParent() != child) {
try {
view = (View) view.getParent();
} catch (ClassCastException e) {
view = null;
}
}
mSelectedPosition = view == null ? -1 : ((ViewGroup) child).indexOfChild(view);
if (DEBUG)
Log.v(TAG, "requestChildFocus focused " + focused + " mSelectedPosition " + mSelectedPosition);
}

Animation rotation off axis

I'm trying to create a custom "loading/throbber" icon for my app. I have an ImageView that points to my "loading" icon:
The problem is the rotation is off axis and looks "wobbly", but I'm not sure what I'm doing wrong:
<ImageView
android:id="#+id/headerReload"
android:src="#drawable/reload"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="5dip"
android:onClick="headerReload_onClick"
android:layout_alignParentRight="true"
/>
public void headerReload_onClick(final View v) {
ImageView searchSpinner = (ImageView)findViewById(R.id.headerReload);
Animation spinnerAnimation = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.loading);
searchSpinner.startAnimation(spinnerAnimation);
}
loading.xml
<?xml version="1.0" encoding="UTF-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="infinite"
android:interpolator="#android:anim/linear_interpolator"
android:duration="1200"
/>
5dp padding on the right side will cause it to rotate unevenly