I have a MotionLayout inside the NestedScrollView:
<androidx.core.widget.NestedScrollView
android:id="@+id/scroll_content"
android:layout_width="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.motion.widget.MotionLayout
android:id="@+id/content_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
app:layoutDescription="@xml/main_scene">
<View 1>
<View 2>
<View 3>
</androidx.constraintlayout.motion.widget.MotionLayout>
My state 1 shows View 1 only.
My state 2 shows View 2 only.
My state 3 shows View 1 + View 2(below View 1) + View 3(below View 2)
Since state 3 appends multiple views vertically, it is the longest vertically.
However, I can only scroll down to the amount set for state 1 & state 2. It does not reset the height inside the scrollView.
Am I doing something wrong?
I tried following at onTransitionCompleted():
scroll_content.getChildAt(0).invalidate()
scroll_content.getChildAt(0).requestLayout()
scroll_content.invalidate()
scroll_content.requestLayout()
They did not solve my issue.
Adding motion:layoutDuringTransition="honorRequest"
inside the <Transition>
in your layoutDescription
XML file fixes the issue.
This was added to ConstraintLayout
in version 2.0.0-beta4
Unfortunately, I also encountered such a problem, but found a workaround
<ScrollView>
<LinearLayout>
<MotionLayout>
and after the animation is completed
override fun onTransitionCompleted(contentContainer: MotionLayout?, p1: Int) {
val field = contentContainer::class.java.getDeclaredField("mEndWrapHeight")
field.isAccessible = true
val newHeight = field.getInt(contentContainer)
contentContainer.requestNewSize(contentContainer.width, newHeight)
}
requestViewSize this is an extension function
internal fun View.requestNewSize(width: Int, height: Int) {
layoutParams.width = width
layoutParams.height = height
layoutParams = layoutParams
}
if you twitch when changing height, just add animateLayoutChanges into your main container and your MotionLayout.
Add if necessary in code
yourView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
--------UPDATE--------
I think I found a more correct option for animating the change in height.
Just the first line in the method onTransitionEnd, insert scroll.fullScroll (ScrollView.FOCUS_UP). I added so that the code for changing the height is executed in 500 milliseconds
override fun onTransitionCompleted(contentContainer: MotionLayout?, currentState: Int) {
if (currentState == R.id.second_state) {
scroll.fullScroll(ScrollView.FOCUS_UP)
GlobalScope.doAfterDelay(500) {
if (currentState == R.id.second_state) {
val field = contentContainer::class.java.getDeclaredField("mEndWrapHeight")
field.isAccessible = true
val newHeight = field.getInt(contentContainer)
contentContainer.requestNewSize(contentContainer.width, newHeight)
}
}
}
}
doAfterDelay is a function extension for coroutine
fun GlobalScope.doAfterDelay(time: Long, code: () -> Unit) {
launch {
delay(time)
launch(Dispatchers.Main) { code() }
}
}
But you can use alitenative
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With