MotionLayout之丝滑动画

MotionLayout是什么

MotionLayout is a new class available in the ConstraintLayout 2.0 library to help Android developers manage motion and widget animation in their application.

MotionLayout怎么用

在使用MotionLayout之前,需要先了解下 ConstraintLayout 布局的使用,ConstraintLayout 完全解析

  1. 引入MotionLayout库
dependencies {
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta2'
}
  1. 使用MotionLayout布局
实现一个简单的DrawerLayout效果

布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene_my_drawer">

    <LinearLayout
        android:id="@+id/my_drawer"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent" >

        <TextView
            android:layout_width="match_parent"
            android:text="my drawer"
            android:layout_height="wrap_content"/>
    </LinearLayout>

</android.support.constraint.motion.MotionLayout>

scene_my_drawer.xml文件

<?xml version="1.0" encoding="utf-8"?><!--describe the animation for activity_motion_sample_step3.xml-->
<!--animate in the path way on a view-->
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- Constraints to apply at the start of the animation -->
    <ConstraintSet android:id="@+id/start">

        <Constraint
            android:id="@id/my_drawer"
            android:layout_width="300dp"
            app:layout_constraintRight_toLeftOf="parent"
            android:layout_height="match_parent">
            <CustomAttribute
                app:attributeName="backgroundColor"
                app:customColorValue="#d81b60" />
        </Constraint>
    </ConstraintSet>
    <!-- Constraints to apply at the end of the animation -->
    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@id/my_drawer"
            android:layout_width="300dp"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_height="match_parent">
            <!-- 实现view自定义属性的变化 -->
            <CustomAttribute
                app:attributeName="backgroundColor"
                app:customColorValue="#9999FF" />
        </Constraint>

    </ConstraintSet>

    <!-- A transition describes an animation via start and end state -->
    <Transition
        app:constraintSetStart="@id/start"
        app:constraintSetEnd="@id/end">

		<!-- 设置手势滑动的方向及作用的空间id -->
        <OnSwipe
            app:dragDirection="dragRight"
            app:touchAnchorId="@id/my_drawer"
            app:touchAnchorSide="right" />
    </Transition>

</MotionScene>

运行结果
在这里插入图片描述

实现一个比较炫酷的效果

布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/scene2">

    <ImageView
        android:id="@+id/bt_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/timg"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.motion.MotionLayout>

scene2.xml文件

<?xml version="1.0" encoding="utf-8"?>
<!--describe the animation for activity_motion_sample_step3.xml-->
<!--animate in the path way on a view-->
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- Constraints to apply at the start of the animation -->
    <ConstraintSet android:id="@+id/start">

        <!--  此文件中 view 的属性优先级比布局文件中高      -->
        <Constraint
            android:id="@id/bt_start"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginStart="12dp"
            android:layout_marginBottom="12dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

        </Constraint>
    </ConstraintSet>
    <!-- Constraints to apply at the end of the animation -->
    <ConstraintSet android:id="@+id/end">
        <!--this view end point should be at bottom of parent-->
        <Constraint
            android:id="@id/bt_start"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_marginBottom="12dp"
            android:layout_marginEnd="12dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent">

        </Constraint>
    </ConstraintSet>

    <!-- A transition describes an animation via start and end state -->
    <Transition
        app:constraintSetStart="@id/start"
        app:duration="2000"
        app:constraintSetEnd="@id/end">

        <KeyFrameSet>
            <!-- <KeyPosition>标签表示在这个点需要做什么;
            framePosition最大值100,表示动画执行的进度;
            keyPositionType表示坐标系,也就是原点的位置;-->
            <KeyPosition
                app:framePosition="20"
                app:motionTarget="@id/bt_start"
                app:keyPositionType="parentRelative"
                app:percentX="1"
                app:percentY="0.5"/>
            <KeyPosition
                app:framePosition="40"
                app:motionTarget="@id/bt_start"
                app:keyPositionType="parentRelative"
                app:percentX="0.5"
                app:percentY="0.75"/>
            <KeyPosition
                app:framePosition="60"
                app:motionTarget="@id/bt_start"
                app:keyPositionType="parentRelative"
                app:percentX="0"
                app:percentY="0.5"/>
            <KeyPosition
                app:framePosition="70"
                app:motionTarget="@id/bt_start"
                app:keyPositionType="parentRelative"
                app:percentX="0.25"
                app:percentY="0.4"/>
            <KeyPosition
                app:framePosition="80"
                app:motionTarget="@id/bt_start"
                app:keyPositionType="parentRelative"
                app:percentX="0.5"
                app:percentY="0.5"/>

            <!--前半段的动画效果:逆时针旋转一圈,同时放大一倍-->
            <KeyAttribute
                app:motionTarget="@id/bt_start"
                android:rotation="-3600"
                android:scaleX="2.0"
                android:scaleY="2.0"
                app:framePosition="50"/>
            <!--后半段的动画效果:逆时针旋转一圈,同时变回原样-->
            <KeyAttribute
                app:motionTarget="@id/bt_start"
                android:rotation="-7200"
                app:framePosition="100"/>
        </KeyFrameSet>

        <OnClick
            app:clickAction="toggle"
            app:targetId="@id/bt_start"/>
    </Transition>

</MotionScene>

运行结果
在这里插入图片描述

联合DrawerLayout,ViewPager,CoordinatorLayout使用

自定义View

package com.boxing.views;
/**
 * Created by liuyuli on 2019-09-02.
 */
public class MyDrawer extends MotionLayout implements DrawerLayout.DrawerListener {

    public MyDrawer(Context context) {
        super(context);
    }

    public MyDrawer(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyDrawer(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void onDrawerSlide(@NonNull View view, float slideOffset) {
        float progress = slideOffset;
        setProgress(progress);
    }

    @Override
    public void onDrawerOpened(@NonNull View view) {
    }

    @Override
    public void onDrawerClosed(@NonNull View view) {
    }

    @Override
    public void onDrawerStateChanged(int i) {
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (getParent() instanceof DrawerLayout) {
            DrawerLayout parent = (DrawerLayout) getParent();
            parent.addDrawerListener(this);
        }
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<com.boxing.views.MyDrawer xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="200dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="@color/colorAccent"
    app:layoutDescription="@xml/scene_drawer">

    <TextView
        android:id="@+id/tv_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="15dp"
        android:text="title 1 title 1"
        android:textColor="#222"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@+id/tv_2"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="15dp"

        android:text="title 2 title 2"
        android:textColor="#222"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@id/tv_3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_1" />

    <TextView
        android:id="@+id/tv_3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="15dp"

        android:text="title 3 title 3"
        android:textColor="#222"
        android:textSize="16sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_2" />

</com.boxing.views.MyDrawer>

scene_drawer.xml文件

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <!-- A transition describes an animation via start and end state -->
    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/tv_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:rotation="90"
            android:translationX="100dp"
            app:layout_constraintBottom_toTopOf="@+id/tv_2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintVertical_bias="0"
            app:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@+id/tv_2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:rotation="90"
            app:layout_constraintVertical_bias="0"
            android:translationX="100dp"
            app:layout_constraintBottom_toTopOf="@id/tv_3"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_1" />
        <Constraint
            android:id="@+id/tv_3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:rotation="90"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintVertical_bias="0"
            android:translationX="100dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_2" />
    </ConstraintSet>

    <!-- Constraints to apply at the start of the animation -->
    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/tv_1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="@+id/tv_2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
        <Constraint
            android:id="@+id/tv_2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toTopOf="@id/tv_3"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_1" />
        <Constraint
            android:id="@+id/tv_3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/tv_2" />
    </ConstraintSet>

    <!-- Constraints to apply at the end of the animation -->
    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@id/start">
    </Transition>

</MotionScene>

运行效果
在这里插入图片描述
参考Introduction to MotionLayout (part I)
Introduction to MotionLayout (part II)
Introduction to MotionLayout (part III)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值