秒懂Android開發之MotionLayout簡單上手

【版權申明】非商業目的註明出處可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/106182408
出自:shusheng007

概述

前段時間升級了Android Studio到4.0, 發現新增了一個動畫編輯器的功能,又一次感嘆Android開發真的是越來越簡單了。看了一下感覺挺有意思,所以就簡單上手一下這個動畫布局MotionLayout,通過這個佈局我們可以以非常簡單的方式作出很炫的動畫。

動畫布局基本元素

先上一張動圖吧,圖中的動畫使用MotionLayout不到兩分鐘就可以完成,在此感謝老婆貢獻自己的美照。

在這裏插入圖片描述
我們只要搞清楚幾個關鍵元素,上手就易如反掌了,當然高級特性還需要熟練後深入探索,這個成年人都明白。

我們可以用一句話來描述一個View的動畫:此View從開始狀態到達結束狀態的一個過程

MotionLayout

MotionLayout是整個動畫的容器,正是它提供了讓其內部的直接嵌套View 做動畫的能力。它是ConstraintLayout 的子類, 可以從AS中通過ConstraintLayout轉換而來。

MotionScene

動畫場景,顧名思義,它的作用就是描述整個動畫。是一個xml文件,放在xml 文件夾內,作爲MotionLayoutlayoutDescription屬性的值,本例中我寫了個一個名爲activity_motion_scene.xml的MotionScence文件並設置給MothionLayout,如下所示

<androidx.constraintlayout.motion.widget.MotionLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
	...
    app:layoutDescription="@xml/activity_motion_scene">
       ...
</androidx.constraintlayout.motion.widget.MotionLayout>

ConstraintSet

動畫開始時或者結束時的快照,其用來描述一個View開始和結束時候的狀態。例如一個View動畫開始前在哪裏,多大尺寸,什麼顏色等等。 其嵌套在MotionScene 裏面,一般有兩個,一個開始一個結束。

<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/my_wife"
            android:layout_width="60dp"
            android:layout_height="60dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />
   </ConstraintSet>
   
   <!--    動畫結束快照-->
   <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/my_wife"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginStart="5dp"
            android:layout_marginEnd="5dp"
            app:layout_constraintStart_toEndOf="@id/my_wife_left"
            app:layout_constraintEnd_toStartOf="@id/my_wife_right"
            app:layout_constraintTop_toTopOf="parent"
            />
    </ConstraintSet>
   ...
</MotionScene>

Transition

描述View從開始狀態變換到結束狀態的過程,且響應用戶的操作,其嵌套在MotionScene 裏,與ConstraintSet平級,是整個動畫布局的精華部分。

Transition 的constraintSetEnd 屬性設置開始ConstraintSet ,constraintSetStart屬性設置結束那個ConstraintSet ,再設置一個動畫時間即可。

其可以包含一個<KeyFrameSet> 負責在動畫過程中改變view的位置和屬性。如果不設置此標籤,那麼我們的動畫就會線性的從開始運動到結束。

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@id/start"
        app:duration="2000">
       <KeyFrameSet>
           <KeyPosition
               app:motionTarget="@id/my_wife_left"
               app:framePosition="40"
               app:keyPositionType="parentRelative"
               app:percentX="0"
               />
           ...
           <KeyAttribute
               app:motionTarget="@id/my_wife"
               app:framePosition="40"
               android:rotationY="360"
               />
       </KeyFrameSet>
        <OnSwipe
            app:touchAnchorId="@+id/my_wife"
            app:touchAnchorSide="top"
            app:dragDirection="dragUp" />
        <OnClick app:targetId="@+id/my_wife" 
           app:clickAction="toggle" />
    </Transition>

MotionLayout基礎使用

明白了以上幾個元素使用就非常簡單了,讓我們完成文章最開始的動畫

  • 配置環境
    需要升級constraintlayout控件庫到2.0以上,現在是beta6了,已經過了alpha,說明接口穩定了。
implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta6"
  • 具體使用
  1. 在layout文件中用MotionLayout 包裹需要做動畫的View。
       <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:layoutDescription="@xml/activity_motion_scene"
    	    app:motionDebug="SHOW_PATH"
    	    tools:context=".animation.MotionActivity">
    	    <ImageView
    	        android:id="@+id/my_wife_left"
    	        android:layout_width="60dp"
    	        android:layout_height="60dp"
    	        android:src="@drawable/my_wife"/>
    	
    	    <ImageView
    	        android:id="@+id/my_wife"
    	        android:layout_width="60dp"
    	        android:layout_height="60dp"
    	        android:src="@drawable/my_wife"/>
    	        
    	    <ImageView
    	        android:id="@+id/my_wife_right"
    	        android:layout_width="60dp"
    	        android:layout_height="60dp"
    	        android:src="@drawable/my_wife" />
    
    </androidx.constraintlayout.motion.widget.MotionLayout>
    
  2. 在res/xml 文件夾中新建一個名爲:activity_motion_scene的MotionScene文件,並設置到MotionLayout的layoutDescription屬性中
  3. 在MotionScene中定義兩個ConstraintSet,一個爲View的開始狀態,一個爲View結束狀態。
  4. 在MotionScene中定義一個Transition,並設置開始與結束的ConstraintSet 。
<MotionScene 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@id/start"
        app:duration="2000">
       <KeyFrameSet>
           <KeyPosition
               app:motionTarget="@id/my_wife_left"
               app:framePosition="40"
               app:keyPositionType="parentRelative"
               app:percentX="0"
               />
           <KeyPosition
               app:motionTarget="@id/my_wife_right"
               app:framePosition="40"
               app:keyPositionType="parentRelative"
               app:percentX="1"
               />
       </KeyFrameSet>
        <!-- 使動畫響應滑動事件-->
        <OnSwipe
            app:touchAnchorId="@+id/my_wife"
            app:touchAnchorSide="top"
            app:dragDirection="dragUp" />
            
        <!-- 使動畫響應點擊事件-->
        <OnClick app:targetId="@+id/my_wife" app:clickAction="toggle" />
    </Transition>

<!--    動畫開始快照-->
    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/my_wife"
            android:layout_width="60dp"
            android:layout_height="60dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />
        <Constraint
            android:id="@+id/my_wife_left"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:alpha="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />
        <Constraint
            android:id="@+id/my_wife_right"
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:alpha="0.0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />
    </ConstraintSet>

<!--    動畫結束快照-->
    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/my_wife_left"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:alpha="1.0"
            app:layout_constraintHorizontal_chainStyle="packed"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toStartOf="@id/my_wife"
            app:layout_constraintTop_toTopOf="@id/my_wife"
            app:layout_constraintBottom_toBottomOf="@id/my_wife"
            />
        <Constraint
            android:id="@+id/my_wife"
            android:layout_width="150dp"
            android:layout_height="150dp"
            android:layout_marginStart="5dp"
            android:layout_marginEnd="5dp"
            app:layout_constraintStart_toEndOf="@id/my_wife_left"
            app:layout_constraintEnd_toStartOf="@id/my_wife_right"
            app:layout_constraintTop_toTopOf="parent"
            />
        <Constraint
            android:id="@+id/my_wife_right"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:alpha="1.0"
            app:layout_constraintStart_toEndOf="@id/my_wife"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="@id/my_wife"
            app:layout_constraintBottom_toBottomOf="@id/my_wife"
            />
    </ConstraintSet>
</MotionScene>
     

經過上面簡單的幾步動畫就已經完成啦,是不是2分鐘內就搞定了。

其中, <Transition>裏的<OnClick>標籤響應用戶的點擊動作,例如此例中我們點擊一下中間的view,動畫就開始了。

<OnClick app:targetId="@+id/my_wife" app:clickAction="toggle" />

擴展

上面只是可以讓你快速上手,裏面還有很多高級特性需要你繼續探索,例如在Transition的 KeyFrameSet 裏面還包括
<KeyCycle><KeyAttribute><KeyTimeCycle><KeyTrigger> 等對動畫精細控制的標籤

下面是一些很好的資源,可以幫助你更加詳細的理解這個庫

本文源碼:AndroidDevMemo

官方示例:ConstraintLayoutExamples
Medium博客: Introduction to MotionLayout

總結

IT 技術更新換代實在是太快了,而且對於應用層會越變越簡單,所以奉勸各位可愛的程序員們在習得日常求生技能後,最好還是多關注一下計算機科學基礎。例如計算機系統、數據結構、算法、數據庫、網絡、編譯原理、設計模式等

總的來說,照目前的情況來看,未來的社會會更加數字化、智能化,所以程序員會大有可爲,加油。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章