如何在 MotionLayout 中为 wrap_content TextView 设置动画?

How to animate a wrap_content TextView in MotionLayout?

首先,我创建了一个minimal demo来演示这个问题。

我想做什么

我的屏幕顶部有 2 个 TextView。第二个在第一个的右边,尺寸较小。两者都显示 API 返回的一些内容(所以我不知道它需要多长时间 - 即它们必须是 wrap_content。)

现在我想实现一个带有过渡效果的粘性header:当用户向上滚动时,第一个TextView会缩小到与第二个几乎相同的大小,并保持自己在屏幕顶部。要实现这一点,MotionLayout 似乎是一个完美的选择。

我的做法

由于我不知道内容的长度,所以为了动画第一个TextView的大小,我只能选择下面的一个:

  1. 动画文本大小
  2. 动画比例

方法 1 可以通过 this 解决方案来完成。但是动画一点都不流畅所以不能用

所以我尝试了方法 2。layoutDescription 文件从

传输第一个 TextView
        <Constraint
                android:id="@+id/tvFirst"
                android:layout_width="wrap_content"
                android:layout_height="32dp"
                app:layout_constraintTop_toBottomOf="@id/vTop"
                app:layout_constraintStart_toStartOf="parent"/>

        <Constraint
                android:id="@+id/tvFirst"
                android:layout_width="wrap_content"
                android:layout_height="24dp"
                app:layout_constraintTop_toBottomOf="@id/vTop"
                app:layout_constraintStart_toStartOf="parent"
                android:transformPivotX="0dp"
                android:transformPivotY="0dp"
                android:scaleX="0.6"
                android:scaleY="0.6"/>

动画效果很好,但是

问题

TextView 的宽度不变。只是它的内容按比例缩小了。这里的问题是,我想让第二个TextView贴在内容的末尾,但是现在它们之间有很大的差距

我尝试了什么

我尝试结合两种方法。即我创建了一个透明 TextView 作为第一个 TextView 的虚拟对象,它使用方法 1 (TextSize) 进行动画处理,并让第二个 TextView 约束到虚拟对象。但是,宽度变化仅在完成过渡后发生,第二个 TextView 在过渡期间仍停留在同一位置。

我的问题

如何使第二个 TextView 紧贴第一个 TextView 内容的末尾顺利地制作动画?

这是一个没有好的解决方案的已知问题。 默认情况下 MotionLayout 块在动画期间中继。 这可以通过标志 Transition:

来改变
 <Transition     motion:layoutDuringTransition="honorRequest" \>

这意味着每次通过时都会解析布局(这很慢),但可能适合您的需要。 另一种方法是使用旨在进行平滑缩放的 MotionLabel。

这是为了减轻缩放量化而设计的 具有属性 scaleFromTextSize

  <androidx.constraintlayout.utils.widget.MotionLabel
    app:textPanX="0"
    app:scaleFromTextSize="40sp"
    android:textSize="90sp"/>

这从大小中抓取文本的“轮廓”并将它们缩放到所需的大小。

从长远来看,我们正在为这个问题寻找更好的解决方案。