以编程方式更改约束时,Android MotionLayout 状态不会更新

odi*_*ity 8 android android-motionlayout

我有一个非常简单的 MotionLayout,我正在尝试以编程方式更改其中一个约束的可见性,并让视图反映该更改。但是,直到我从当前状态过渡然后再回到它时,更改才会反映出来。你如何让视图根据新的约束立即更新?我试过updateState()rebuildScene()invalidate()但他们都不做任何事情。

这是视图:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motion_layout"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:showIn="@layout/activity_main"
        app:layoutDescription="@xml/motion_scene"
        tools:context=".MainActivity">

    <TextView
            android:id="@+id/left_to_right_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Left to right"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

    <TextView
            android:id="@+id/top_to_bottom_text"
            android:text="Top to bottom"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.motion.widget.MotionLayout>
Run Code Online (Sandbox Code Playgroud)

这是运动场景:

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:app="http://schemas.android.com/apk/res-auto">


    <Transition
            app:constraintSetStart="@id/base"
            app:constraintSetEnd="@id/bottom">
        <OnClick
                app:targetId="@id/top_to_bottom_text">

        </OnClick>

    </Transition>

    <Transition
            app:constraintSetStart="@id/base"
            app:constraintSetEnd="@id/right">
        <OnSwipe
                app:dragDirection="dragRight"
                app:touchAnchorId="@id/left_to_right_text"
                app:touchAnchorSide="right">

        </OnSwipe>

    </Transition>


    <ConstraintSet android:id="@+id/base">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/bottom">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintBottom_toBottomOf="parent"
        />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/right">

        <Constraint
                android:id="@id/left_to_right_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>

        <Constraint
                android:id="@id/top_to_bottom_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent"/>
    </ConstraintSet>
</MotionScene>
Run Code Online (Sandbox Code Playgroud)

这是我尝试在 2 秒后更新文本视图之一的可见性的代码:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        Completable.timer(2, TimeUnit.SECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                motion_layout.getConstraintSet(R.id.base)?.let {
                    it.setVisibility(R.id.left_to_right_text, View.INVISIBLE)
                }
                motion_layout.updateState()
                // These don't work either
//                motion_layout.rebuildScene()
//                motion_layout.invalidate()
            }
    }
Run Code Online (Sandbox Code Playgroud)

您可以在下面的 gif 中看到,我等待了 2 秒钟,但没有任何反应。直到我转换到一个新状态,然后回到原来的状态,可见性才会更新。

Lio*_*IAm 14

我找到了解决办法!

Phan Van Linh 提供的解决方案对我不起作用(我使用的是 2.0.0-beta1 约束版本)

只需在您刚刚更改可见性(或其他视图属性)的视图上调用 .requestLayout() 所以在您的示例中:

motion_layout.getConstraintSet(R.id.base)?.let {
                it.setVisibility(R.id.left_to_right_text, View.INVISIBLE)
                yourView.requestLayout() // <-- this line
            }
Run Code Online (Sandbox Code Playgroud)

由于 requestLayout 方法的文档,它将遍历当前在布局传递中的所有视图的层次结构。