MotionLayout 似乎在动画期间失去了一些约束

MotionLayout seems to lose some constraints during animation

我有一个问题: 我有一个 TextView,其内容通过 LiveData 不断变化。当动画不执行时这看起来没问题,但当 MotionLayout 开始执行时,我的文本被挡住了一点点。 而且我的TextView和Button的constraints都被packed了

activity:

class ErrorActivity : AppCompatActivity() {

    private val mViewModel by viewModels<ErrorViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        DataBindingUtil.setContentView<ActivityErrorBinding>(this, R.layout.activity_error).apply {
            lifecycleOwner = this@ErrorActivity
            viewModel = mViewModel
        }
    }

    fun startStopAnim(v: View) {
        mViewModel.anim()
    }
}

activity布局:

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

    <data>

        <variable
            name="viewModel"
            type="com.test.test.ErrorViewModel" />

    </data>

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene"
        binding:anim="@{viewModel.mAnim}">

        <TextView
            android:id="@+id/tv"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{@string/test(viewModel.mCountDown)}"
            android:textSize="32sp"
            app:layout_constraintEnd_toStartOf="@+id/btn"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="@string/test" />

        <Button
            android:id="@+id/btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Test"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@+id/tv"
            app:layout_constraintTop_toTopOf="parent" />

        <Button
            android:id="@+id/anim"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="startStopAnim"
            android:text="startOrStop"
            android:textAllCaps="false"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.motion.widget.MotionLayout>
</layout>

视图模型:

class ErrorViewModel : ViewModel() {

    private val _countDown: MutableLiveData<String> = MutableLiveData()
    val mCountDown: LiveData<String> = _countDown

    private val _anim: MutableLiveData<Boolean> = MutableLiveData()
    val mAnim: LiveData<Boolean> = _anim

    private var count = 0
    private var state = false

    init {
        viewModelScope.launch(Dispatchers.IO) {
            while (true) {
                delay(1000)
                _countDown.postValue(count++.toString())
            }
        }
    }

    fun anim() {
        state = !state
        _anim.value = state
    }
}

@BindingAdapter("anim")
fun anim(layout: MotionLayout, play: Boolean?) {
    play?.let {
        if (it) {
            layout.transitionToEnd()
        } else {
            layout.transitionToStart()
        }
    }
}

运动场景:

为简单起见,场景只有一个持续时间

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto">
    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="2000" />
</MotionScene>

gif 正如您在 gif 中看到的,当没有点击时,数字一切正常,但是当我点击按钮时,一个 2 秒的动画开始,在此期间我的文本无法正确显示。 当然,这只是一个演示示例。在真实场景中,不仅文字显示不完整,连TextView和ImageView都错位了,动画一旦执行就无法恢复。 谁能帮帮我...

实际上在真实场景中,有问题的TextView(A)的父布局(B)会执行位移动画。这个动画只要执行一次,TextView A的约束关系肯定会出问题,无法恢复(目前找到onPause后onResume可以恢复)

动画期间的设计使 MotionLayout 不支持 requestLayout。 因为在大多数应用程序中不需要它并且会对性能产生重大影响。

要在转换中启用它,请添加

<Transition  ...   motion:layoutDuringTransition="honorRequest" \>