11

我在 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>

我的状态 1 仅显示视图 1。
我的状态 2 仅显示视图 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()

他们没有解决我的问题。

4

2 回答 2

2

motion:layoutDuringTransition="honorRequest"在XML 文件中添加<Transition>可以解决问题。layoutDescription这是ConstraintLayout在版本中添加的2.0.0-beta4

于 2020-12-08T14:38:02.850 回答
1

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

<ScrollView>
  <LinearLayout>
   <MotionLayout>

并且在动画完成后

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 这是一个扩展函数

internal fun View.requestNewSize(width: Int, height: Int) {
   layoutParams.width = width
   layoutParams.height = height
   layoutParams = layoutParams
}

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

必要时在代码中添加

yourView.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)

- - - - 更新 - - - -

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

就在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)
                    }
                }
            }
        }

doAfterDelay 是协程的函数扩展

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

但是你可以使用 altenative

于 2019-11-01T13:32:14.247 回答