MotionLayout忽略填充

时间:2020-01-29 22:33:27

标签: android animation padding android-motionlayout

我正在尝试在滑动时为textview的边距,填充和Alpha设置动画。 一开始,textview没有填充,alpha为1。 最后,我希望alpha为0,填充为100dp,两侧为16dp dp余量,alpha为0.5 一切正常,除了填充没有改变。 MotionLayout是否支持填充? 我正在使用androidx.constraintlayout:constraintlayout:2.0.0-beta4。

添加更多文本,因为SO表示我的帖子看起来大部分是代码... 添加更多文本,因为SO表示我的帖子看起来主要是代码... 添加更多文本,因为SO表示我的帖子看起来主要是代码...

布局xml:

    <androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/layoutParent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/test">

    <TextView
        android:id="@+id/fakenavigationBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="hello world">
    </TextView>
</androidx.constraintlayout.motion.widget.MotionLayout>

动作场景:

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

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@id/fakenavigationBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="1"
            android:padding="100dp"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="parent">
        </Constraint>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/fakenavigationBar"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:alpha="0.5"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintBottom_toBottomOf="parent">
        </Constraint>

    </ConstraintSet>

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end"
        motion:duration="2000"
        motion:motionInterpolator="linear">

        <OnSwipe
            motion:touchAnchorId="@+id/fakenavigationBar"
            motion:touchAnchorSide="top"
            motion:dragDirection="dragDown"/>
    </Transition>
</MotionScene>

enter image description here enter image description here

3 个答案:

答案 0 :(得分:3)

我承认这不是一个非常有用的答案,但是我在填充方面也遇到了同样的问题。边距对于MotionLayout似乎可以正常工作,但似乎不支持填充。我要做的是使我的工作达到我想要的样子,就是将MotionLayout文件中的填充添加到所需的任何视图中。它考虑了该文件中的填充,但不考虑“运动场景约束集”中的填充,因此在我的情况下无法对填充进行动画处理。它将只保留在MotionLayout文件中设置的静态填充,这足以让我通过。

this blog post看来,如果将Motion Scene过渡设置为在两个不同的布局之间(而不是ConstraintSet)之间,则可以在填充之间设置动画。

我已经向几个不同的资源问了一个问题,为什么MotionLayout不支持填充,如果我得到了有用的信息,它将更新我的答案,但据我所知,MotionLayout不支持动画填充值。 / p>

答案 1 :(得分:2)

这是MotionLayout的一个限制

Padding 不是受支持的属性 ConstraintSet,因此不支持它。 View setPaddingTop 甚至没有方法,因此不能将它们视为自定义属性。

这是 MotionLayout 中的一个空白,但存在填充问题。填充会随着视图尺寸的变化而更改请求布局的视图测量尺寸。 这很昂贵,因为解析动画的唯一方法是解析开始和结束约束集并重建插值。

最好重新设计布局以使用边距,因为这是布局的控件。

答案 2 :(得分:0)

这是可能的,但显然会付出很大的性能代价。

向您的 MotionLayout.TransitionListener 添加一个 MotionLayout,用于计算给定进度值 (0f-1f) 的正确填充值,并将其设置为您在 onTransitionChange() 中的视图:

motionLayout.setTransitionListener(object : MotionLayout.TransitionListener {
    override fun onTransitionStarted(motionLayout: MotionLayout, startId: Int, endId: Int) { }

    override fun onTransitionChange(motionLayout: MotionLayout, startId: Int, endId: Int, progress: Float) {
        val paddingInPx = calculatePaddingPx(progress)
        myView.setPadding(paddingInPx, paddingInPx, paddingInPx, paddingInPx)
    }

    override fun onTransitionCompleted(motionLayout: MotionLayout, currentId: Int) { }

    override fun onTransitionTrigger(motionLayout: MotionLayout, triggerId: Int, positive: Boolean, progress: Float) { }
})

在您的 MotionScene 中,添加:

<Transition motion:layoutDuringTransition="honorRequest"/>

另见:https://github.com/androidx/constraintlayout/issues/7#issuecomment-721447209

编辑 1:虽然我能够用这种技术改变填充,但我最终决定不使用它,因为性能影响在旧设备上非常明显。

Edit 2: 还有一个与滚动动画相关的问题,如果你做一个投掷,那么 TransitionListener 回调不能保证被调用,所以过渡将达到它的开始/结束状态没有更新填充。