ConstraintLayout 2.0新特性 MotionLayout制作炫酷動畫 [復制鏈接]

2019-8-13 17:31
一碼到底 閱讀:1344 評論:1 贊:2
Tag:  

在今年的Google I/O 上 Google 開發者展示了這么一段視頻 What’s New in ConstraintLayout (Google I/O’19) (視頻在youtube上,需要翻墻),截了其中一段做了個gif圖



圖中動畫使用ConstraintLayout 2.0里的MotionLayout完成。


ConstraintLayout 2.0現在還是beta版,不過已經可以實行圖中的動畫了。


今天可以做一個簡易版的動畫。


本項目環境配置:

Android Studio 3.4.1

ConstraintLayout 2.0.0-beta1


新建項目,引入ConstraintLayout 庫

implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'


布局根節點使用MotionLayout替換ConstraintLayout


<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_motion"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="20dp"
    app:layoutDescription="@xml/motion_scene"
    app:showPaths="true"
    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/main_image1"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/color1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription" />


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


xml里引入motion_scene文件:


<?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="4000"
        motion:motionInterpolator="easeInOut">

        <OnClick
            motion:clickAction="toggle"
            motion:targetId="@id/main_image1" />


            ......
            ......

    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/main_image1"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:drawPath="path"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:pathMotionArc="startVertical" />

    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/main_image1"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent" />


    </ConstraintSet>

</MotionScene>


我們先從最簡單的入手,定義一個ImageView,兩個ConstraintSet 分別定義開始位置和結束位置,然后在Transition處引入:


motion:duration 定義動畫時長


motion:motionInterpolator定義緩動動畫 (這里推薦一個網站 緩動函數速查表)

http://www.xuanfengge.com/easeing/easeing/


<OnClick
            motion:clickAction="toggle"
            motion:targetId="@id/main_image1" />


這段代碼 表示監聽main_image1的點擊事件,并在開始位置和結束位置之間切換狀態



為了使圖片旋轉一周,我們需要定義5個關鍵點



先添加第一個關鍵點


<KeyFrameSet>

            <KeyPosition
                motion:framePosition="20"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="flip"
                motion:percentX="0.25"
                motion:percentY="0.65" />


        </KeyFrameSet>



motion:motionTarget 表示關鍵點應用的控件

motion:framePosition 表示這個點處于動畫進行到20%時

motion:keyPositionType 表示使用的坐標系,有三種選擇


  1. parentRelative

  2. deltaRelative

  3. pathRelative


motion:percentX motion:percentX 關鍵點的(x,y)坐標


三種坐標系的區別


parentRelative


這個我使用后發現與引用的博客里不一樣,這個是與Android坐標系一致,以父容器左上角為坐標原點,向右為x軸正方向,向下為y軸正方向。


deltaRelative


以控件開始位置和結束位置定義坐標系,開始位置為坐標原點,水平方向為X軸,垂直方向為Y軸。



pathRelative


以起始位置為坐標原點,起始位置到結束位置的path為X軸,垂直方向為Y軸。



motion:pathMotionArc 表示兩點之間的path形狀,默認是none(線性) ,flip表示翻轉當前弧形方向


startHorizontal



startVertical



第一個關鍵點定義完成后運行如圖



如此這樣,定義完其他的關鍵點:


<KeyFrameSet>

            <KeyPosition
                motion:framePosition="20"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="flip"
                motion:percentX="0.25"
                motion:percentY="0.65" />

            <KeyPosition
                motion:framePosition="36"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="flip"
                motion:percentX="0"
                motion:percentY="0.5" />

            <KeyPosition
                motion:framePosition="52"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="startHorizontal"
                motion:percentX="0.5"
                motion:percentY="0.25" />

            <KeyPosition
                motion:framePosition="68"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="startVertical"
                motion:percentX="1"
                motion:percentY="0.5" />

            <KeyPosition
                motion:framePosition="84"
                motion:keyPositionType="parentRelative"
                motion:motionTarget="@id/main_image1"
                motion:pathMotionArc="none"
                motion:percentX="0.5"
                motion:percentY="0.75" />


        </KeyFrameSet>


運行效果如下:



添加其他的ImageView,更改最后的顯示位置,將ImageView1的關鍵點復制3份,分別設成其他的ImageView的關鍵點:


<ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/main_image1"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:drawPath="path"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:pathMotionArc="startVertical" />


        <Constraint
            android:id="@+id/main_image2"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:drawPath="path"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:pathMotionArc="startVertical" />

        <Constraint
            android:id="@+id/main_image3"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:drawPath="path"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:pathMotionArc="startVertical" />

        <Constraint
            android:id="@+id/main_image4"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:drawPath="path"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toRightOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:pathMotionArc="startVertical" />


    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/main_image1"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toLeftOf="parent"
            motion:layout_constraintRight_toLeftOf="@id/main_image2"
            motion:layout_constraintVertical_chainStyle="spread_inside" />

        <Constraint
            android:id="@+id/main_image2"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toRightOf="@id/main_image1"
            motion:layout_constraintRight_toLeftOf="@id/main_image3" />

        <Constraint
            android:id="@+id/main_image3"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toRightOf="@id/main_image2"
            motion:layout_constraintRight_toLeftOf="@id/main_image4" />

        <Constraint
            android:id="@+id/main_image4"
            android:layout_width="60dp"
            android:layout_height="60dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintLeft_toRightOf="@id/main_image3"
            motion:layout_constraintRight_toRightOf="parent" />


    </ConstraintSet>


效果如下:



可以看到效果和演示視頻差不多了,接下來使4個ImageView依次運動


更改每個ImageView的每個motion:framePosition,使各個關鍵點產生距離,最終效果如下



代碼已上傳github github地址

https://github.com/LGD2009/MotionLayoutExample


新增欄目每日一問


View的onAttachedToWindow ,onDetachedFromWindow 調用時機,使用場景是什么?

答案or 回答:https://wanandroid.com/wenda/show/8488



參考文章:


  1. MotionLayout 基礎教程

    https://juejin.im/post/5cadc1ba6fb9a0686e40bb82

  2. 「譯」MotionLayout 介紹 (part II)

    https://juejin.im/post/5c1c8f74f265da61682b591c

  3. Defining motion paths in MotionLayout

    https://medium.com/google-developers/defining-motion-paths-in-motionlayout-6095b874d37


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(1)
tv2014 2019-8-14 15:40
不錯,很棒
回復
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

两码中特期期