状态更改后,ScrollView中的MotionLayout不会更新高度

jcl*_*ova 6 android android-scrollview android-motionlayout

我在NestedScrollView内部有一个MotionLayout:

<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>
Run Code Online (Sandbox Code Playgroud)

我的状态1仅显示“视图1”。
我的状态2仅显示View 2。
我的状态3显示了“视图1” +“视图2”(在“视图1”之下)+“视图3”(在“视图2”之下)

由于状态3垂直附加了多个视图,因此它是垂直最长的。

但是,我只能向下滚动到为状态1和状态2设置的数量。它不会重置scrollView内部的高度。

难道我做错了什么?

我尝试过以下onTransitionCompleted():

scroll_content.getChildAt(0).invalidate()
scroll_content.getChildAt(0).requestLayout()
scroll_content.invalidate()
scroll_content.requestLayout()
Run Code Online (Sandbox Code Playgroud)

他们没有解决我的问题。

小智 1

不幸的是,我也遇到了这样的问题,但找到了解决方法

<ScrollView>
  <LinearLayout>
   <MotionLayout>
Run Code Online (Sandbox Code Playgroud)

动画完成后

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)
        }
Run Code Online (Sandbox Code Playgroud)

requestViewSize 这是一个扩展函数

internal fun View.requestNewSize(width: Int, height: Int) {
   layoutParams.width = width
   layoutParams.height = height
   layoutParams = layoutParams
}
Run Code Online (Sandbox Code Playgroud)

如果您在更改高度时抽搐,只需将 animateLayoutChanges 添加到主容器和 MotionLayout 中即可。

如果需要的话在代码中添加

yourView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
Run Code Online (Sandbox Code Playgroud)

- - - - 更新 - - - -

我想我找到了一个更正确的选项来动画高度的变化。

只需在onTransitionEnd方法的第一行,插入scroll.fullScroll(ScrollView.FOCUS_UP)即可。我添加了这样改变高度的代码在500毫秒内执行

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)
                    }
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

doAfterDelay 是协程的函数扩展

fun GlobalScope.doAfterDelay(time: Long, code: () -> Unit) {
    launch {
        delay(time)
        launch(Dispatchers.Main) { code() }
    }
}
Run Code Online (Sandbox Code Playgroud)

但你可以使用替代