【问题标题】:MotionLayout inside the ScrollView does not update the height after the state changeScrollView里面的MotionLayout在状态改变后不更新高度
【发布时间】:2019-06-12 18:22:48
【问题描述】:

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

他们没有解决我的问题。

【问题讨论】:

    标签: android android-scrollview android-motionlayout


    【解决方案1】:

    &lt;Transition&gt;layoutDescription XML 文件中添加 motion:layoutDuringTransition="honorRequest" 可解决此问题。 这是在 2.0.0-beta4 版本中添加到 ConstraintLayout

    【讨论】:

    • 当我想在动画期间更新 Motion Layout 中的某些视图时,它有助于解决我的问题。没有它,子视图的 requestLayout 调用将被父运动布局忽略,并且这些视图的尺寸不会更新。使用“honorRequest”解决了这个问题。
    【解决方案2】:

    很遗憾,我也遇到了这样的问题,但是找到了解决方法

    <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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-03
      • 2020-03-06
      • 1970-01-01
      • 2022-12-18
      • 2016-04-15
      • 2016-10-02
      • 2019-11-30
      • 2017-01-01
      相关资源
      最近更新 更多