'Motion Layout reset on navigating between activities
I am using motion layout in my mainactivity. It is working proplerly. However when I move to other activities and navigate back to my mainactivity sometimes the activity is reset and the layout is in its starting state.How do I keep this from happening ? Apart from this I also have another question about motion layout which I have asked here
Solution 1:[1]
What I did was adding a field, a boolean field to be specific and use the life cycle to handle it.
private var hasMotionScrolled = false
override fun onResume() {
super.onResume()
if (hasMotionScrolled) motionLayout.progress = MOTION_TRANSITION_COMPLETED
}
override fun onPause() {
super.onPause()
hasMotionScrolled = motionLayout.progress > MOTION_TRANSITION_INITIAL
}
companion object {
private const val MOTION_TRANSITION_COMPLETED = 1F
private const val MOTION_TRANSITION_INITIAL = 0F
}
So in my case, motion layout is doing an animation related to scrolling. If this is not your case maybe you can use directly the motionLayout.progress
. My problem with using the progress
directly was that intermediate states would make other elements not visible when navigating back, that is why implemented an all or nothing boolean flag.
I don't see this as a clean solution, a flag is always something that means something else could have been better, if you can find something official, please let me know in the comments.
Solution 2:[2]
You have to save/restore the progress of your MotionLayout:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putFloat("progress", motionLayout.progress)
}
override fun onCreate(savedInstanceState: Bundle?) {
...
if (savedInstanceState != null)
motionLayout.progress = savedInstanceState.getFloat("progress", 0f)
...
}
Solution 3:[3]
This is how I do it with Fragment
Create an instance variable on your Fragment
class:
var motionProgress = 0f // 0f being initial state
On your onViewCreated
function, give the current value to the layout:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.motionLayout.progress = motionProgress
}
Finally, when navigating away from the Fragment
, update the value of motionProgress
on function onPause
:
override fun onPause() {
super.onPause()
motionProgress = binding.motionLayout.progress
}
Solution 4:[4]
You can add a transition listener to the motion layout & save a flag when the transition is completed. Afterwards, when the activity gets recreated, you can read that flag and use smth like:
motionLayout.setState(R.id.end, ConstraintSet.WRAP_CONTENT, ConstraintSet.WRAP_CONTENT)
Where R.id.end is the id from constraintSetEnd property.
Solution 5:[5]
class ExtMotionLayout : MotionLayout {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun onSaveInstanceState(): Parcelable? {
return SavedState(progress, super.onSaveInstanceState())
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state is SavedState) {
progress = state.progress
super.onRestoreInstanceState(state.superState)
} else super.onRestoreInstanceState(state)
}
class SavedState : BaseSavedState {
val progress: Float
constructor(progress: Float, source: Parcelable?) : super(source) {
this.progress = progress
}
constructor(superState: Parcel) : super(superState) {
progress = superState.readFloat()
}
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeFloat(progress)
}
}
}
Solution 6:[6]
class CustomMotionLayout(context: Context, attrs: AttributeSet) : MotionLayout(context, attrs) {
init {
isSaveEnabled = true
}
override fun onSaveInstanceState(): Parcelable {
return SavedState(progress, super.onSaveInstanceState())
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state is SavedState) {
progress = state.progress
super.onRestoreInstanceState(state.superState)
} else super.onRestoreInstanceState(state)
}
class SavedState(val progress: Float, source: Parcelable?) : BaseSavedState(source) {
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeFloat(progress)
}
}
}
Use CustomMotionLayout
instead of default MotionLayout
Just keep in mind to provide id to your motion layout
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | cutiko |
Solution 2 | kroegerama |
Solution 3 | cutiko |
Solution 4 | Thkru |
Solution 5 | ???????? ?????? |
Solution 6 | Reyaz Ahmad |