MotionLayout 真有点儿东西!

·  阅读 2821
MotionLayout 真有点儿东西!

简介

  MotionLayout作为Google发布的新动画组件可谓是解决了部分Java/Kotlin代码编写动画代码的痛点,它是ConstraintLayout的子类允许其在不同状态之间设置布局动画,发布于版本ConstraintLayout2.0之后,最低支持到API 14的Android系统。

注意:目前MotionLayout无法与推崇的声明式UI JetpackCompose一起使用

引入

implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
复制代码

结构&基本用法

MotionLayout在XML布局中需要去设置layoutDescription属性该属性对应的在res/xml中创建一个以<MotionScene></MotionScene>为Root的元素标签

MotionLayout 下定义的view若要做动画需要在直接子集,不能嵌套若需求,则需要嵌套动画组件 代码示例:activity_you_tube_layout.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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/motionlayout"
    android:background="#666"
    app:layoutDescription="@xml/activity_you_tube_layout_scene">
    </androidx.constraintlayout.motion.widget.MotionLayout>
复制代码

代码示例:res/xml/activity_you_tube_layout_scene.xml
要知道scene的文件结构

<Transition android:id="@+id/container_transition_elsp"
        app:constraintSetEnd="@+id/youtube_end"
        app:constraintSetStart="@+id/youtube_start"
        app:duration="500"
        app:motionInterpolator="easeInOut">
        <OnSwipe/>
        <OnClick/>
        <KeyFrameSet>
            <KeyPosition/>
            <KeyAttribute/>
            ...
        </KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/youtube_hide_state">
    <Constrain>
        ...
        <CustomAttribute/>
    </Constrain>
</ConstraintSet>
复制代码

MotionScene需要有一个或多个Transition标签,它承载着动画的开始与结束。

Transition:

  • constraintSetEnd 记录动画结束的布局文件结构
  • constraintSetStart 记录动画开始时的布局文件结构
  • duration 过度时间
  • motionInterpolator 动画差值器 OnSwipe:
    解释:指定当用户在布局上滑动时要执行的操作。动画序列的速度和目标视图的动画受滑动速度和方向的影响,具体取决于您使用可选参数设置的限制
  • touchAnchorId 在滑动之后移动的视图
  • touchAnchorSide 滑动所固定到的目标视图的一侧。MotionLayout 将尝试在该固定点与用户手指之间保持恒定的距离。可接受的值包括 "left"、"right"、"top" 和 "bottom"。
  • dragDirection 用户滑动动作的方向。如果设置了此属性,此 onSwipe 将仅适用于沿特定方向的滑动。可接受的值包括 "dragLeft"、"dragRight"、"dragUp" 和 "dragDown"。
  • maxAcceleration 目标视图的最大加速度。
  • dragScale 控制视图相对于滑动长度的移动距离。默认值为 1,表明视图移动的距离应与滑动距离一致。 OnClick:
    解释:指定当用户点按特定视图时要执行的操作。
  • targetId 受监控的视图。当用户点按此视图时,将会发生转换。
  • ClickAction 点按视图时要执行的操作。 KeyFrameSet
    解释关键帧可以包含多个KeyPosition与多个KeyAttribute
    KeyPosition
    解释: 指定视图在运动序列中特定时刻的位置。该属性用于调整默认的运动路径。
  • motionTarget 需要作出改变的视图Id.
  • framePosition1 到 99 之间的整数,用于指定运动序列中视图何时到达此 <KeyPosition> 指定的点。
  • percentX & percentY 指定视图应到达的位置。keyPositionType 属性指定如何解释这些值。
  • keyPositionType
    • parentRelative percentX 和 percentY 是相对于父视图
    • deltaRelative percentX 和 percentY 是相对于视图在整个运动序列过程中移动的距离 KeyAttribute
      解释:设置关键帧的控制视图的标准属性例如: visibility,alpha,elevation,rotation,等...
  • motionTarget 需要作出改变的视图Id.
  • framePosition1 到 99 之间的整数,用于指定运动序列中视图何时到达此 <KeyPosition> 指定的点。
  • View的各种标准属性,android:visibility,alpha等 ConstraintSet
    解释:指定所有视图在动画序列中某一点上的位置和属性。通常,一个 <Transition> 元素可指向两个 <ConstraintSet> 元素,其中一个定义动画序列的开始,另一个定义结束。 Constraint
    解释:指定运动序列其中一个元素的位置和属性。元素支持一组标准 ConstraintLayout 属性
  • id 绑定的View Id CustomAttribute
    解释:位于Constraint下的标签,表示自定义属性
  • attributeName 例如:app:attributeName=“BackgroundColor” 表示该view的背景颜色需要改变
  • customColorValue 例如:app:customColorValue="#FF0000"背景颜色红色 ...有很多属性详情可以查看国外文档国内文档

示例Demo1

文件: activity_scan4.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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:showPaths="true"
    tools:context=".Scan4Activity"
    app:layoutDescription="@xml/activity_scan4_scene">
    <View
        android:id="@+id/button"
        android:background="@color/colorAccent"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:text="Button" />
</androidx.constraintlayout.motion.widget.MotionLayout>
复制代码

定义需要变化的View务必要给出一个Id并且这个View是MotionLayout的直接子View在动画文件中需要将其绑定
动画文件:activity_scan4_scene.xml

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#D81B60" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            app:layout_constraintEnd_toEndOf="parent">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#9999FF" />
        </Constraint>
    </ConstraintSet>

    <Transition
        app:motionInterpolator="linear"
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@+id/start"
        app:duration="1000">
        <OnSwipe
            app:dragDirection="dragRight"
            app:touchAnchorId="@id/button"
            app:touchAnchorSide="right" />
        <KeyFrameSet>
            <KeyAttribute
                android:rotation="-45"
                android:scaleX="2"
                android:scaleY="2"
                app:framePosition="30"
                app:motionTarget="@id/button" />
            <KeyPosition
                app:framePosition="90"
                app:keyPositionType="pathRelative"
                app:motionTarget="@id/button"
                app:percentY="-0.3" />
        </KeyFrameSet>
    </Transition>
</MotionScene>
复制代码
  1. Constraint中的id必须与其布局文件中的view Id一致,定义两个ConstraintSet标签,一个是起始动画布局一个是结束动画布局分别设置id为endstart,然后将其id设置到Transition标签的constraintSetEndconstraintSetStart中,再接着过渡时间以及差值器等。
  2. Constraint中可以看到在起始与结束分别设置了view的各个状态,一个是布局View改变的位置,一个是布局View改变的背景颜色
  3. OnSwipe设置了可拖拽进行动画进度调整的view
  4. KeyFrameSet中设置了两个关键帧的设置,分别是KeyAttribute设置在动画进度为30%的时候改变了Idbutton的view的旋转角度-45以及大小为原来倍的状态属性,KeyPosition在90%的时候改变了view的行经路线,以相对path进行改变 Y坐标轴变为-0.3也就是向上移动

具体如何计算以及过渡这个其实我们不需要关心,框架已经帮我们做了 最终效果

demo1.gif

当完成这个案例之后基本对这个动画组件以及定义方式大概都知道了,那么直接做一个漂亮的动效也不是不可以!

这个实现好牛逼.jpeg

示例Demo2

文件:activity_you_tube_layout.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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/motionlayout"
    android:background="#666"
    app:layoutDescription="@xml/activity_you_tube_layout_scene"
    tools:context=".YouTubeScanActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/container_q"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="80dp"
        android:background="#fff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <ImageView
        android:id="@+id/image_small"
        android:layout_width="120dp"
        android:scaleType="centerCrop"
        android:layout_height="0dp"
        android:src="@drawable/sunset2"
        app:layout_constraintBottom_toBottomOf="@id/container_q"
        app:layout_constraintTop_toTopOf="@id/container_q" />

    <ImageView
        android:id="@+id/play_image"
        android:clickable="true"
        android:background="?selectableItemBackground"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="@id/container_q"
        app:layout_constraintTop_toTopOf="@id/container_q"
        app:srcCompat="@drawable/ic_play_arrow_gray_32dp" />

    <ImageView
        android:background="?selectableItemBackground"
        android:id="@+id/play_clear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="@id/container_q"
        app:layout_constraintTop_toTopOf="@id/container_q"
        app:srcCompat="@drawable/ic_clear_gray_32dp" />
    <TextView
        android:id="@+id/text_row"
        android:textSize="13sp"
        android:lines="1"
        android:ellipsize="end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:text="This is a text in an item"
        />
    <androidx.core.widget.NestedScrollView
        android:id="@+id/recyclerview"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#fff"
        app:layout_constraintBottom_toBottomOf="@id/container_q"
        app:layout_constraintEnd_toEndOf="@id/container_q"
        app:layout_constraintStart_toStartOf="@id/container_q">

       ...重复

    </androidx.core.widget.NestedScrollView>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/main_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#fff"
        app:layout_constraintBottom_toBottomOf="@id/bottom_navigation"
        app:layout_constraintTop_toTopOf="parent"/>


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#fff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_nav_menu" />


</androidx.constraintlayout.motion.widget.MotionLayout>
复制代码

动画文件: res/xml/activity_you_tube_layout_scene.xml

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ConstraintSet android:id="@+id/youtube_start">
        <Constraint
            android:id="@+id/container_q"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="75dp"
            android:elevation="5dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#fff" />
        </Constraint>
        <Constraint
            android:id="@+id/text_row"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/play_image"
            app:layout_constraintStart_toEndOf="@id/image_small"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/image_small"
            android:layout_width="120dp"
            android:layout_height="0dp"
            android:elevation="6dp"
            android:scaleType="centerCrop"
            android:src="@drawable/sunset2"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintStart_toStartOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/play_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="50dp"
            android:alpha="1"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/play_clear"
            app:layout_constraintTop_toTopOf="@id/container_q" />

        <Constraint
            android:id="@+id/play_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:alpha="1"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/recyclerview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintStart_toStartOf="@id/container_q">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#fff" />
        </Constraint>
        <Constraint
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="#fff"
            android:translationY="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_nav_menu" />
        <Constraint
            android:id="@+id/main_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#fff"
            app:layout_constraintBottom_toTopOf="@id/bottom_navigation"
            app:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/youtube_end">
        <Constraint
            android:id="@+id/container_q"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginStart="0dp"
            android:layout_marginEnd="0dp"
            android:layout_marginBottom="0dp"
            android:elevation="5dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@+id/recyclerview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintStart_toStartOf="@id/container_q"
            app:layout_constraintTop_toBottomOf="@id/image_small">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#fff" />

        </Constraint>
        <Constraint
            android:id="@+id/play_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="100dp"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/image_small"
            android:layout_width="0dp"
            android:layout_height="300dp"
            android:elevation="6dp"
            android:scaleType="centerCrop"
            android:src="@drawable/sunset2"
            app:layout_constraintStart_toStartOf="@id/container_q"
            app:layout_constraintTop_toBottomOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />

        <Constraint
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:background="#fff"
            android:translationY="60dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_nav_menu" />
        <Constraint
            android:id="@+id/main_recyclerview"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:background="#fff"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <Transition
        android:id="@+id/container_transition_elsp"
        app:constraintSetEnd="@+id/youtube_end"
        app:constraintSetStart="@+id/youtube_start"
        app:duration="500"
        app:motionInterpolator="easeInOut">
        <OnSwipe
            app:dragDirection="dragUp"
            app:touchAnchorId="@id/image_small"
            app:touchAnchorSide="top" />
        <KeyFrameSet>
            <KeyPosition
                app:curveFit="linear"
                app:framePosition="5"
                app:keyPositionType="parentRelative"
                app:motionTarget="@id/image_small"
                app:percentWidth="1"
                app:percentX="0" />
            <KeyPosition
                app:curveFit="linear"
                app:framePosition="30"
                app:motionTarget="@id/container_q"
                app:percentWidth="1" />
            <KeyPosition
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/recyclerview"
                app:percentWidth="1" />

            <KeyAttribute
                android:alpha="0"
                app:curveFit="linear"
                app:framePosition="0"
                app:motionTarget="@id/recyclerview" />
            <KeyAttribute
                android:alpha="0"
                app:curveFit="linear"
                app:framePosition="40"
                app:motionTarget="@id/recyclerview" />
            <KeyAttribute
                android:alpha="1"
                app:curveFit="linear"
                app:framePosition="100"
                app:motionTarget="@id/recyclerview" />
            <KeyAttribute
                android:alpha="0"
                app:curveFit="linear"
                app:framePosition="30"
                app:motionTarget="@id/play_image" />
            <KeyAttribute
                android:alpha="0"
                app:curveFit="linear"
                app:framePosition="30"
                app:motionTarget="@id/play_clear" />
            <KeyAttribute
                android:alpha="0"
                app:curveFit="linear"
                app:framePosition="10"
                app:motionTarget="@id/text_row" />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="30"
                app:motionTarget="@id/container_q"

                />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/recyclerview"

                />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/play_image"

                />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/play_clear"

                />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/image_small" />
            <KeyAttribute
                android:translationY="-100dp"
                app:curveFit="linear"
                app:framePosition="50"
                app:motionTarget="@id/text_row" />
        </KeyFrameSet>
    </Transition>

    <Transition
        android:id="@+id/container_transition_hide_show"
        app:constraintSetEnd="@+id/youtube_hide_state"
        app:constraintSetStart="@+id/youtube_start"
        app:duration="300"
        app:motionInterpolator="easeIn" />
    <ConstraintSet android:id="@+id/youtube_hide_state">
        <Constraint
            android:id="@+id/container_q"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="-60dp"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#fff" />
        </Constraint>
        <Constraint
            android:id="@+id/image_small"
            android:layout_width="120dp"
            android:layout_height="0dp"
            android:alpha="0"
            android:elevation="6dp"
            android:scaleType="centerCrop"
            android:src="@drawable/sunset2"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintStart_toStartOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/play_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="50dp"
            android:alpha="0"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/play_clear"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/text_row"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="10dp"
            android:layout_marginEnd="10dp"
            android:alpha="0"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/play_image"
            app:layout_constraintStart_toEndOf="@id/image_small"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/play_clear"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="16dp"
            android:alpha="0"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintTop_toTopOf="@id/container_q" />
        <Constraint
            android:id="@+id/recyclerview"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:alpha="0"
            android:elevation="6dp"
            app:layout_constraintBottom_toBottomOf="@id/container_q"
            app:layout_constraintEnd_toEndOf="@id/container_q"
            app:layout_constraintStart_toStartOf="@id/container_q">
            <CustomAttribute
                app:attributeName="BackgroundColor"
                app:customColorValue="#fff" />
        </Constraint>

    </ConstraintSet>
</MotionScene>
复制代码
  1. 里面的属性上面以及说过了,很好理解的,KeyPosition中有写app:percentWidth此属性是targetView的宽度比例在百分之X进度的时候进行转换

  2. 还是基本的view的改变alphatransitionY/X/Z以及ConstraintLayout约束中的位置的变化等

  3. 当然这里面有两个Transition标签,这样在xml中可能无法正确选择相应的动画,接下来就需要MotionLayout代码进行控制了,此代码也很简单,下文中有写!

  4. 布局完成之后是动画起始布局这样一个布局:

demo2_start.png
5. 动画结束布局

demo2_end.png

...
假设已经完成相应的数据填充工作

在效果图中最终看到点击底部悬浮栏会进行转场动画,然后点击关闭底部悬浮栏下移透明隐藏,他们分别对应的Transitionid 是container_transition_elspcontainer_transition_hide_show有了这两个Id在代码中即可使用有选择性的进行动画操作.

Java代码:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_you_tube_layout);
         motionLayout = findViewById(R.id.motionlayout);
         //设置motionlayout动画为container_transition_hide_show 
         motionLayout.setTransition(R.id.container_transition_hide_show);
         //将其底部悬浮栏隐藏进度设置1->进度:100% 直接隐藏
         motionLayout.setProgress(1);
         //省略部分代码
         ...
         //containerQ 为悬浮栏id
         containerQ.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //同理设置动画布局文件中TransitionId
                motionLayout.setTransition(R.id.container_transition_elsp);
                //判断当前动画start/end id是否是transition对应的start/end Id
                if (motionLayout.getCurrentState() == R.id.youtube_end) {
                    //结束->起始 动画操作
                    motionLayout.transitionToStart();
                } else { 
                    ////起始->结束 动画操作
                    motionLayout.transitionToEnd();
                }

            }
        });
        //悬浮栏的关闭按钮 执行隐藏动画
        clearImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            //同理
                motionLayout.setTransition(R.id.container_transition_hide_show);
                if (motionLayout.getCurrentState() == R.id.youtube_start) {
                    motionLayout.transitionToEnd();
                } else {
                    motionLayout.transitionToStart();
                }
            }
        });
 }
复制代码

setTransitiontransitionToEndtransitionToStartgetCurrentState()等都是motionlayout公有方法可在文档中查阅并使用

最终效果

jjmeut.gif

最后

看到这里本篇内容已经完成了

感谢各位客官的浏览,有什么不对的地方欢迎指正

分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改