Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/215.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android运动布局运动交错_Android_Animation_Layout_Motion - Fatal编程技术网

Android运动布局运动交错

Android运动布局运动交错,android,animation,layout,motion,Android,Animation,Layout,Motion,我试图使用MotionLayout设置视图的动画,但希望在其他约束之前设置某些约束的动画。我认为这就是动议的目的:交错过渡属性,但我不明白它是如何工作的,而且在任何地方都没有成功工作的例子。在MotionLayout的更新版本中,似乎我们应该为单个约束设置motion:motionStagger,但我似乎无法使其按照所需设置为stagger。我能找到的唯一文档是解释增强的交错API,但我不知道如何使用它 我在下面添加了我的MotionLayout代码。作为参考,我使用的是ConstraintLa

我试图使用MotionLayout设置视图的动画,但希望在其他约束之前设置某些约束的动画。我认为这就是动议的目的:交错过渡属性,但我不明白它是如何工作的,而且在任何地方都没有成功工作的例子。在MotionLayout的更新版本中,似乎我们应该为单个约束设置motion:motionStagger,但我似乎无法使其按照所需设置为stagger。我能找到的唯一文档是解释增强的交错API,但我不知道如何使用它

我在下面添加了我的MotionLayout代码。作为参考,我使用的是ConstraintLayout的
2.0.0-beta3'
版本

<?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">
<Transition
    motion:constraintSetEnd="@+id/end"
    motion:constraintSetStart="@+id/start"
    motion:duration="300"
    motion:motionInterpolator="easeInOut"
    motion:staggered="0.4" />

<ConstraintSet android:id="@+id/start">
    <Constraint android:id="@id/translucentOverlay">
        <Layout
            android:layout_width="5dp"
            android:layout_height="5dp"
            motion:layout_constraintBottom_toBottomOf="@id/imageBorder"
            motion:layout_constraintEnd_toEndOf="@id/imageBorder"
            motion:layout_constraintStart_toStartOf="@id/imageBorder"
            motion:layout_constraintTop_toTopOf="@id/imageBorder" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/imageBorder">
        <Layout
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginBottom="8dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <CustomAttribute
            motion:attributeName="crossfade"
            motion:customFloatValue="0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/imageBackground">
        <Layout
            android:layout_width="32dp"
            android:layout_height="32dp"
            motion:layout_constraintBottom_toBottomOf="@id/imageBorder"
            motion:layout_constraintEnd_toEndOf="@id/imageBorder"
            motion:layout_constraintStart_toStartOf="@id/imageBorder"
            motion:layout_constraintTop_toTopOf="@id/imageBorder" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/profileInitialText">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            motion:layout_constraintBottom_toBottomOf="@id/imageBackground"
            motion:layout_constraintEnd_toEndOf="@id/imageBackground"
            motion:layout_constraintStart_toStartOf="@id/imageBackground"
            motion:layout_constraintTop_toTopOf="@id/imageBackground" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/profileImage">
        <Layout
            android:layout_width="32dp"
            android:layout_height="32dp"
            motion:layout_constraintBottom_toBottomOf="@id/imageBackground"
            motion:layout_constraintEnd_toEndOf="@id/imageBackground"
            motion:layout_constraintStart_toStartOf="@id/imageBackground"
            motion:layout_constraintTop_toTopOf="@id/imageBackground" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/name">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="128dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
        <Motion motion:motionStagger="5" />
    </Constraint>

    <Constraint android:id="@id/description">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/name" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
        <Motion motion:motionStagger="5" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint android:id="@id/translucentOverlay">
        <Layout
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/imageBorder">
        <Layout
            android:layout_width="88dp"
            android:layout_height="88dp"
            motion:layout_constraintBottom_toBottomOf="@id/imageBackground"
            motion:layout_constraintEnd_toEndOf="@id/imageBackground"
            motion:layout_constraintStart_toStartOf="@id/imageBackground"
            motion:layout_constraintTop_toTopOf="@id/imageBackground" />
        <CustomAttribute
            motion:attributeName="crossfade"
            motion:customFloatValue="1" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/imageBackground">
        <Layout
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_marginTop="64dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/profileInitialText">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            motion:layout_constraintBottom_toBottomOf="@id/imageBackground"
            motion:layout_constraintEnd_toEndOf="@id/imageBackground"
            motion:layout_constraintStart_toStartOf="@id/imageBackground"
            motion:layout_constraintTop_toTopOf="@id/imageBackground" />
        <Motion motion:motionStagger="2" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="0.0" />
    </Constraint>
    <Constraint android:id="@id/profileImage">
        <Layout
            android:layout_width="70dp"
            android:layout_height="70dp"
            motion:layout_constraintBottom_toBottomOf="@id/imageBackground"
            motion:layout_constraintEnd_toEndOf="@id/imageBackground"
            motion:layout_constraintStart_toStartOf="@id/imageBackground"
            motion:layout_constraintTop_toTopOf="@id/imageBackground" />
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/name">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/profileImage" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="5" />
    </Constraint>

    <Constraint android:id="@id/description">
        <Layout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:layout_marginEnd="16dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toBottomOf="@id/name" />
        <CustomAttribute
            motion:attributeName="alpha"
            motion:customFloatValue="1.0" />
        <Motion motion:motionStagger="5" />
    </Constraint>
</ConstraintSet>


交错排列的实际数学可能有点混乱,但在实践中

交错 正在设置动画的每个视图都会指定一个Stager值(应用程序:motionStagger) 默认情况下,视图的参差值是与视图列表中最顶部视图的曼哈顿距离。可以通过属性手动设置该值 这将为每个使用motionStagger标记的视图指定一个浮点参差值(未标记的视图将被忽略)。首先启动具有最低浮点值(V0)的视图。最后启动具有最高浮点值(Vn)的视图

  • 对于交错值S(Vi)的任何视图
  • 过渡交错值为TS(从0.0到1.0)
  • 动画的持续时间为持续时间
  • 视图动画持续时间DS=持续时间*(1-TS)
  • 调用交错分数SFi=(S(Vi)-S(V0))/(S(Vn)-S(V0))
  • 视图在:(持续时间DS)*SFi开始设置动画
这个数学可能令人困惑。这是一个实际的例子 如果我有3个视图View1、View2、View3,我将motionStagger分别设置为2、5和7,并将动画持续时间设置为5秒。 当我将转换交错设置为0.4时,将按如下方式进行:

The animation duration is 3.0 sec = 5 * (1- 0.4)

View1 stagger fraction = 0 = (2-2)/(7-2)
View1 starts at 0.0 sec 
View1 end    at 3.0 sec (0.0 + 3.0)

View2 stagger fraction = 0.6 = (5-2)/(7-2)
View2 starts at 1.2 sec (5.0-3.0) * 0.6
View2 ends   at 4.2 sec 1.2 + 3.0

View3 stagger fraction = 1
View3 starts at 2.0 sec (5.0 - 3.0) * 1
View3 ends   at 5.0 sec 

好吧,在经历了很长一段时间的尝试和错误之后,研究了发布更新中给出的公式,这就是我所想到的

上面的链接文章给了我们一些令人困惑的方程,它们是

Let
运动参差值为S(Vi)
整体参差值为参差(从0.0到1.0)
动画的持续时间为持续时间
视图动画持续时间=持续时间*(1-交错)
视图在持续时间*(参差-参差*(S(Vi)-S(V0))/(S(Vn)-S(V0))开始设置动画。

确定过渡交错值:

要确定希望整体错开的位置,请考虑尝试错开的视图数量。 我上面链接的文章指出,
viewDuration=totalDuration*(1-stagger)
因此我们可以将这个等式重新排列为
stagger=1-(viewDuration/totalDuration)
。在我的例子中,因为我希望在视图进入时有三个不同的时刻,所以我希望我的
viewDuration/totalDuration
大约是
1/3
。为了简化计算,我选择将参差设置为
0.6
,使每个视图的持续时间为400。因此,我的转换代码如下所示

<Transition
    motion:constraintSetEnd="@+id/end"
    motion:constraintSetStart="@+id/start"
    motion:duration="1000"
    motion:motionInterpolator="easeInOut"
    motion:staggered="0.6" />
这肯定有点复杂,但我可以用我的例子来说明

所以在我的例子中,我们已经讨论了如何有三个视图,我希望它们在某种程度上均匀地错开(这就是为什么我们选择0.6的错开值)。根据下面等式的逆结构,我知道具有最高
motionStagger
值的视图将首先设置动画

假设我们有三个视图,一个我想排在第一位的ImageView,一个我想排在第二位的TextView,还有一个我想排在第三位的按钮。因此,我将为ImageView指定一个motionStagger值3,为TextView指定一个motionStagger值2,为TextView指定一个motionStagger值1。让我们在这里进行计算:

Stagger value = 0.6
motionStaggerValues = 3 (for ImageView), 2 (for TextView), and 1(for Button) 
ImageView animationStartTime = 1000 * (0.6 - 0.6 * ((3-1)/(3-1)))
    = 1000 * (0.6 - 0.6 * (1)) = 1000 * 0 = 0
因此,ImageView从0开始设置动画,并设置400毫秒的动画(如上一节所示)。 现在,让我们计算TextView

Stagger value = 0.6
motionStaggerValues = 3 (for ImageView), 2 (for TextView), and 1(for Button) 
TextView animationStartTime = 1000 * (0.6 - 0.6 * ((2-1)/(3-1)))
    = 1000 * (0.6 - 0.6 * (1/2)) = 1000 * 0.3 = 300
因此,TextView从300开始设置动画,并设置400毫秒的动画

最后,让我们计算按钮的开始时间:

Stagger value = 0.6
motionStaggerValues = 3 (for ImageView), 2 (for TextView), and 1(for Button) 
TextView animationStartTime = 1000 * (0.6 - 0.6 * ((1-1)/(3-1)))
    = 1000 * (0.6 - 0.6 * (0)) = 1000 * 0.6 = 600
因此,按钮在600开始设置动画,并在400毫秒内设置动画

这些值可以根据您选择的运动交错值进行移动和交错。为了便于解释,我试着让这个尽可能简单,但它可能会变得非常复杂,这取决于您试图完成的任务。下面是我上面概述的示例的最终代码

<ConstraintSet android:id="@+id/start">
    <Constraint android:id="@id/imageView">
        ...
        <Motion motion:motionStagger="3" />
    </Constraint>

    <Constraint android:id="@id/textView">
        ...
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/button">
        ...
        <Motion motion:motionStagger="1" />
    </Constraint>
</ConstraintSet>

...
...
...

其中,您将需要另一个用于结束状态的并行约束集

这对数学分解很有帮助!我正在尝试实现它,但似乎无法在背景/图像之后获得要设置动画的名称/文本。我在问题中添加了我的运动场景代码。我遗漏了什么?有趣的是,我运行这个测试时,在我的视图上输入了精确的值,首先输入的是motionStagger设置为7的值,最后输入的是motionStagger设置为2的值。似乎你的数学在某个地方有点不对劲。谢谢你的帮助。分解它让我对如何进行有了更好的想法!是的,我可能把它倒过来了。这将是-0.4的行为。对于0.4的sta
<ConstraintSet android:id="@+id/start">
    <Constraint android:id="@id/imageView">
        ...
        <Motion motion:motionStagger="3" />
    </Constraint>

    <Constraint android:id="@id/textView">
        ...
        <Motion motion:motionStagger="2" />
    </Constraint>

    <Constraint android:id="@id/button">
        ...
        <Motion motion:motionStagger="1" />
    </Constraint>
</ConstraintSet>