后羿:我射箭了快上—用MotionLayout實現王者榮耀團戰

前言

昨晚跟往常同樣,飯後開了一局王者榮耀,前中期基本焦灼,到了後期一波決定勝負的時候,我果斷射箭,射中對面,配合隊友直接秒殺,打贏團戰一波推完基地。那叫一個精彩,隊友都發出了666666的稱讚,我酷酷的點了一下抱拳:多謝!嘿嘿java

賽後,手機上正在展現個人MVP動畫,我不由思考,這麼精彩的團戰我怎麼能不記錄下來?恰好最近了解到MotionLayout庫,就用它實現吧😂。android

動畫效果

motionlayout-demo.gif

功能詳解

MotionLayout 是一種佈局類型,可幫助您管理應用中的運動和微件動畫。MotionLayout 是 ConstraintLayout 的子類,在其豐富的佈局功能基礎之上構建而成。git

如上述介紹,MotionLayoutConstraintLayout的子類,至關於加了動畫功能的ConstraintLayout。MotionLayout做爲一個動畫控件的好處就在於基本不用寫java代碼,所有在xml文件中搞定。並且咱們只須要設定起始位置,結束位置以及一些中間狀態,就能自動生成動畫。github

先分析下咱們的團戰,主要分爲三個場景web

  • 后羿果斷射大,射中在 瘋狂走位的亞瑟。
  • 妲己和鍾無豔同時在草叢蹲伏,看到后羿的精彩射箭,從 草叢走出,準備大戰。
  • 妲己 2技能暈眩住對面的魯班七號,一套技能加上鍾無豔的 大招,將對面兩個英雄KO。

場景一

包含控件:后羿,亞瑟,魯班,后羿的箭動畫描述:走位的亞瑟,后羿射箭面試

首先在佈局文件中,添加第一個MotionLayout,並添加上全部的控件,后羿和魯班因爲是靜止狀態,因此要寫上位置約束,其餘包含動畫的控件能夠暫時不用寫位置約束:微信

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motionLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_01"
        app:showPaths="false"
        tools:showPaths="true">

        <ImageView
            android:id="@+id/houyi"
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:layout_marginLeft="180dp"
            android:src="@drawable/houyi_model"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.8" />

        <ImageView
            android:id="@+id/houyi_arrow"
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:src="@drawable/arrow" />

        <ImageView
            android:id="@+id/yase"
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:src="@drawable/yase_model" />

        <ImageView
            android:id="@+id/luban"
            android:layout_width="66dp"
            android:layout_height="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.58"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.26"
            android:src="@drawable/luban_model" />

    </androidx.constraintlayout.motion.widget.MotionLayout>

因爲MotionLayout繼承自ConstraintLayout,因此能夠用ConstraintLayout的屬性。這裏能夠看到有兩個新的屬性:app

  • app:layoutDescription,這個屬性就是表明該MotionLayout對應的動畫場景,引用的是一個 MotionScene(XML資源文件),其中就會包括相應佈局的全部運動動畫描述。
  • app:showPaths,這個屬性表明運動進行時是否顯示運動路徑,也就是全部動畫的路徑是否顯示。默認是false。代碼中也是能夠設置是否顯示動畫路徑, setDebugMode方法傳入 MotionLayout.DEBUG_SHOW_PATH屬性便可。
后羿射箭

接下來就能夠寫動畫場景(MotionScene)了,新建res-xml-scene_01.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">

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="2000">

    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/houyi_arrow"
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:layout_marginLeft="190dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.8">

        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/houyi_arrow"
            android:layout_width="66dp"
            android:layout_height="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.65"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.35">
        </Constraint>
    </ConstraintSet>

</MotionScene>

能夠看到,MotionScene有兩個主要的標籤TransitionConstraintSetide

  • Transition,包括運動的基本定義,其中 motion:constraintSetStartmotion:constraintSetEnd指的是運動的起始狀態和結束狀態。分別就對應下面ConstraintSet所配置的。 app:duration表明完成運動所需的時間。
  • ConstraintSet,多個控件的端點約束集合,好比這裏就有兩個ConstraintSet,分別表明起始約束集和結束約束集。

其中Constraint屬性指定了端點位置中某一個元素的位置和屬性:

  • 支持全部 ConstraintLayout 屬性。
  • 支持 alpha,rotation,visibility,translationX,scaleX等view基本屬性。
  • 支持自定義屬性,用子標籤 CustomAttribute表示,舉個小栗子:
    <Constraint
        android:id="@+id/button" ...>
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#D81B60"/>
    </Constraint>
   

attributeName屬性就是與具備gettersetter方法的對象匹配,好比這裏的backgroundColor就對應了view自己的基本方法getBackgroundColor()setBackgroundColor()

好了,回到後裔這邊,因爲后羿的箭是從后羿位置到亞瑟位置,因此咱們設定好后羿箭的兩個端點狀態,配置好後,MotionLayout就會自動幫咱們生成從起始狀態到結束狀態的動畫了,后羿箭從后羿位置飛到了亞瑟位置。等等,運行怎麼沒反應呢?動畫怎麼觸發啊?

Motion提供了三動畫觸發方法:1)onClick標籤,表示點擊場景中的某個控件來觸發動畫效果。其中有兩個屬性。

  • app:targetId,表示要觸發動畫的視圖
  • app:clickAction,表示點擊的效果,例如,toggle(循環動畫),transitionToStart(過渡到開始狀態)

2)OnSwipe標籤,表示經過用戶輕觸控制動畫,有點手勢滑動的感受

  • app:touchAnchorId,表示能夠滑動並拖動的視圖。
  • app:touchAnchorSide 表示從哪邊開始拖動。
  • app:dragDirection 表示拖動的進度方向。例如,dragRight表示當向右拖動(滑動)。
  • app:onTouchUp 表示手勢擡起的時候動做。例如,stop表示手勢擡起的時候view動畫中止。

3)java代碼控制.

  • motionLayout.transitionToEnd(),過渡動畫到結束位置。
  • motionLayout.setTransitionListener,監聽動畫。

這裏咱們就設置點擊后羿觸發動畫:

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

好了,運行,點擊后羿,后羿的箭成功射出去了。

可是這還不夠,后羿箭到亞瑟位置確定就會消失了,怎麼表示這個消失呢?用透明度,直接設置結束位置的透明度爲0就會消失了。

      android:alpha="0"

看看效果:

houyi_arrow_alhpa.gif

好像仍是有點不對,箭在空中的時候就消失了,咱們要的效果是射到亞瑟才消失。這是由於生成動畫的時候是按照起始點到結束點過渡的流程平均分配到每一個時間點,因此他就會從一開始就慢慢線性變化透明度,直到徹底消失。

怎麼辦呢?就要用到關鍵幀KeyFrameSet了。

KeyFrameSet關鍵幀,能夠設定動畫過程當中的某個關鍵位置或屬性。設定關鍵幀後,MotionLayout會平滑地將視圖從起點移至每一箇中間點,而後移至最終目標位置。因此這裏,咱們須要設置兩個關鍵屬性, 1)快射到亞瑟的時候,箭的透明度仍是1。2)射到亞瑟的時候,透明度改爲0。

        <KeyFrameSet>
            <KeyAttribute
                app:framePosition="98"
                app:motionTarget="@id/houyi_arrow"
                android:alpha="1" />
            <KeyAttribute
                app:framePosition="100"
                app:motionTarget="@id/houyi_arrow"
                android:alpha="0" />
        </KeyFrameSet>

KeyAttribute就是設置關鍵屬性的標籤,其中

  • app:framePosition 表示該關鍵幀的位置,至關於百分比。
  • app:motionTarget 表示做用於那個視圖

這樣設置好,后羿箭的動畫也就完成了。

瘋狂走位的亞瑟

到亞瑟了,亞瑟的動畫效果是走位走位被射中。因此先設定好亞瑟的位置,從遠處走到被射中的位置。

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/houyi_arrow"
            android:layout_width="66dp"
            android:layout_height="66dp"
            android:layout_marginLeft="190dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.8">

        </Constraint>

        <Constraint
            android:id="@+id/yase"
            android:layout_width="66dp"
            android:layout_height="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.8"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.2">

        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/houyi_arrow"
            android:layout_width="66dp"
            android:layout_height="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.65"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.35">

        </Constraint>

        <Constraint
            android:id="@+id/yase"
            android:layout_width="66dp"
            android:layout_height="66dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.65"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.35">

        </Constraint>
    </ConstraintSet>

能夠看到,一個端點狀態,能夠放置多個控件屬性。

放好亞瑟的起始和結束狀態後,再設定瘋狂走位,怎麼弄?——KeyCycle

KeyCycle,循環關鍵幀,能夠給動畫添加振動,其實就是波形圖,好比sin,cos。這裏咱們就設定一個sin曲線給亞瑟,做爲走位的路徑。也是放到關鍵幀KeyFrameSet標籤下。

    <KeyCycle
        android:translationY="50dp"
        app:framePosition="70"
        app:motionTarget="@id/yase"
        app:wavePeriod="0.5"
        app:waveShape="sin" />
  • app:waveShape  表示波動類型,好比sin,cos
  • app:wavePeriod表示波動週期,好比0.5就表示半個sin週期,能夠理解爲震動0.5次。

好了,第一個場景搞定,看看效果:

場景二

包含控件:妲己,鍾無豔動畫描述:從草叢走出來的妲己和鍾無豔

這一個場景主要是描述在草叢蹲伏的妲己和鍾無豔,看到后羿射箭後,走出草叢準備接技能。直接上代碼:

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motionLayout2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_02"
        tools:showPaths="true">


        <ImageView
            android:id="@+id/daji"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:src="@drawable/daji_model" />

        <ImageView
            android:id="@+id/zhongwuyan"
            android:layout_width="75dp"
            android:layout_height="75dp"
            android:src="@drawable/zhongwuyan_model" />

    </androidx.constraintlayout.motion.widget.MotionLayout>


//scene_02.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">

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="2000">

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

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/daji"
            android:layout_width="80dp"
            android:layout_height="80dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.75"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.85">

        </Constraint>

        <Constraint
            android:id="@+id/zhongwuyan"
            android:layout_width="70dp"
            android:layout_height="70dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.25"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.1">

        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/daji"
            android:layout_width="80dp"
            android:layout_height="80dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.65"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.65">

        </Constraint>

        <Constraint
            android:id="@+id/zhongwuyan"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.42"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.2">

        </Constraint>
    </ConstraintSet>

</MotionScene>
        

這裏,我想給鍾無豔一個異形走位,就是先在草叢裏走,再出來。這時候就要用到另外一個關鍵幀標籤——KeyPosition

KeyPosition,表示關鍵幀的位置,也就是動畫必經的一個點。該屬性用於調整默認的運動路徑。

1) motion:percentX、motion:percentY指定視圖應到達的位置。keyPositionType 屬性指定如何解釋這些值。

2) keyPositionType有三種設置

  • parentRelative,相對於父視圖的位置,x爲橫軸(0左-1右),y爲縱軸(0頂-1底)好比要設置位置到右端中部位置,就設定app:percentY="0.5" app:percentX="1"便可。
  • deltaRelative,相對於視圖在整個運動序列過程當中移動的距離,(0,0)爲視圖起始位置,(1,1)爲結束位置。x爲橫軸,y爲縱軸
  • pathRelative,x軸方向爲視圖在路徑範圍內移動的方向,0位視圖起始位置,1爲結束位置(即x軸爲起點和終點的鏈接線)。y軸垂直於x軸,正值爲路徑左側,負值爲右側。因此,這個和deltaRelative相比,就是x軸和Y軸的不一樣,相同的是都是按照起始位置到結束位置爲參考。

這裏咱們給鍾無豔一個parentRelative。

    <KeyPosition
        app:motionTarget="@id/zhongwuyan"
        app:framePosition="30"
        app:keyPositionType="parentRelative"
        app:percentY="0"
        app:percentX="0.4"
        />

最後加上兩個英雄從草叢走出來,由半透明到不透明的過程:

            <KeyAttribute
                app:framePosition="0"
                app:motionTarget="@id/daji"
                android:alpha="0.7" />
            <KeyAttribute
                app:framePosition="70"
                app:motionTarget="@id/daji"
                android:alpha="1" />

            <KeyAttribute
                app:framePosition="0"
                app:motionTarget="@id/zhongwuyan"
                android:alpha="0.7" />
            <KeyAttribute
                app:framePosition="60"
                app:motionTarget="@id/zhongwuyan"
                android:alpha="1" />

場景三

包含控件:妲己的一技能,妲己的二技能,鍾無豔動畫描述:鍾無豔閃現到人羣中使用大招轉轉轉,妲己二技能暈眩住魯班,一技能跟上。

鍾無豔閃現,我用的是消失再出現的方式,也就是改變alpha。鍾無豔的大招,用到的是android:rotationY,設定繞y軸旋轉。

妲己的一技能和二技能都是用的普通位置移動,注意控制透明度也就是出現和消失便可。上代碼:

//scene_03.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">

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="4000">

        <KeyFrameSet>

            <!-- 鍾無豔-->
            <KeyAttribute
                app:framePosition="20"
                app:motionTarget="@id/zhongwuyan2"
                android:rotationY="0" />

            <KeyAttribute
                app:framePosition="1"
                app:motionTarget="@id/zhongwuyan"
                android:alpha="1" />

            <!-- 妲己2技能-->

            <KeyPosition
                app:motionTarget="@id/daji_2"
                app:framePosition="20"
                app:keyPositionType="deltaRelative"
                app:percentY="0"
                app:percentX="0"
                />

            <KeyAttribute
                app:framePosition="20"
                app:motionTarget="@id/daji_2"
                android:alpha="1" />

            <KeyPosition
                app:motionTarget="@id/daji_2"
                app:framePosition="60"
                app:keyPositionType="deltaRelative"
                app:percentY="1"
                app:percentX="1"
                />

            <KeyAttribute
                app:framePosition="40"
                app:motionTarget="@id/daji_2"
                android:alpha="1" />

            <KeyAttribute
                app:framePosition="61"
                app:motionTarget="@id/daji_2"
                android:alpha="0" />


            <!-- 妲己1技能-->

            <KeyAttribute
                app:framePosition="55"
                app:motionTarget="@id/daji_1"
                android:alpha="1" />

            <KeyPosition
                app:motionTarget="@id/daji_1"
                app:framePosition="55"
                app:keyPositionType="deltaRelative"
                app:percentY="0"
                app:percentX="0"
                />

            <KeyAttribute
                app:framePosition="85"
                app:motionTarget="@id/daji_1"
                android:alpha="1" />

        </KeyFrameSet>

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

     //。。。
</MotionScene>
        

想看完整源代碼的能夠文末附件📎自取。

實際應用場景

其實作下來能夠發現,Motionlayout實現動畫真的很簡便,大大提升了開發效率,這也是jetpack組件開發的初心。可是,Motionlayout仍是有缺點的,好比直接經過xml代碼的狀況下,沒法設置動畫的銜接,設定動畫的前後順序。因此到底motionlayout應用場景是什麼呢?

motionlayout做爲一個過渡動畫,應該適用於一些控件切換,界面變化之類的動畫。好比DrawerLayout,viewpager切換的時候,能夠設置一些view過渡的動畫。官網有一個相似youtube中運動動畫的案例,我這邊搬過來簡單說下。先看看效果

youtube-motion2.gif

效果不錯吧,特別是手勢滑動的那個絲滑感,太爽了,之前作這種動畫效果少說也要半個小時吧,想一想就頭疼。如今,MotionLayout:so easy

來一塊兒分析下:

包含控件:頂部佈局控件topLayout(包含頂部圖片topImage,播放按鈕topPlay,關閉按鈕topClose),中部佈局midlayout(包含文字部分midView),下部菜單控件bottomView

動畫描述(某些具體數值由代碼中得知):

  • topLayout從上方依附parent位置,變化到下方bottomView的上方。高度由320dp變成54dp。
  • topImage從滿鋪父佈局,到最後長度不滿鋪(長度設置爲高度2.5倍),高度距離父佈局上下2dp。關鍵幀:到90%進度的時候,仍是滿鋪,再慢慢縮小長度。
  • topPlay,topClose從不顯示(alhpa爲0)到最後顯示徹底(alhpa爲1)。關鍵幀:到90%進度的時候,不透明仍是爲10%(alpha0.1),再慢慢變不透明。
  • midlayout,白色佈局,從底部依附父佈局到bottomView的上方,這個layout是爲了讓toplayout下來的時候更加天然,由於recycleview會變徹底透明,就須要這個白色佈局過渡,讓動畫更完整。
  • midView,從toplayout下方位置到最後和toplayout重合,透明度從不透明到徹底透明。關鍵幀:到75%進度的時候,就徹底透明。
  • bottomView,從父佈局視圖下面(看不到)到父佈局底部(看得見)

就這麼多,分析好每一個佈局的起始位置,結束位置,再調整一下關鍵幀。一個跟隨手勢滑動的過渡動畫布局就完成了。貼下MotionScene關鍵代碼,想看完整源代碼能夠去文末附件自取,官網案例和個人demo都包含。


<?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="1000"
        motion:motionInterpolator="linear">

        <OnSwipe
            motion:dragDirection="dragUp"
            motion:touchAnchorId="@+id/top_image_container"
            motion:touchAnchorSide="bottom" />

        <KeyFrameSet>
            <KeyPosition
                motion:curveFit="linear"
                motion:framePosition="90"
                motion:motionTarget="@id/top_image"
                motion:percentWidth="0"
                motion:percentX="0" />
            <KeyPosition
                motion:curveFit="linear"
                motion:framePosition="90"
                motion:motionTarget="@id/top_image_container"
                motion:percentWidth="0" />

            <KeyPosition
                motion:curveFit="linear"
                motion:framePosition="90"
                motion:motionTarget="@id/recyclerview_container"
                motion:percentWidth="0" />

            <KeyAttribute
                android:alpha="0"
                motion:framePosition="75"
                motion:motionTarget="@id/recyclerview_front" />

            <KeyAttribute
                android:alpha="0.10"
                motion:framePosition="90"
                motion:motionTarget="@id/image_clear" />

            <KeyAttribute
                android:alpha="0.10"
                motion:framePosition="90"
                motion:motionTarget="@id/image_play" />
        </KeyFrameSet>
    </Transition>

</MotionScene>

這裏有幾個新屬性說下:

  • motion:curveFit,表示用哪一種線條軌跡通過該關鍵幀,默認是曲線(spline),更加圓滑。這是設置的linear爲直線過渡,由於自己就是直線,因此沒什麼影響。
  • motion:percentWidth,表示視圖相對大小,取值爲0-1,0表明初始位置寬度,1表明結束位置寬度。這裏爲0就表明寬度到該位置仍是和初始寬度一致。
  • motion:motionInterpolator,表示動畫的插值器。這裏的linear就是線性運動,還能夠設置bounce彈簧運動等等。

關於過渡動畫

關於過渡動畫,其實以前也是存在的——TransitionManagerTransitionManager能夠提供不一樣場景之間的過渡轉換動畫,須要設定兩個場景(佈局文件),而後兩個場景中對應的控件id要對應上。最後經過java代碼執行過渡動畫。

上個代碼:

//兩個場景的佈局
    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/scene_root">

        <include layout="@layout/a_scene" />
    </FrameLayout>
    
//場景一
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="26sp"
        android:id="@+id/text_view1"
        android:text="Text Line 1" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="26sp"
        android:id="@+id/text_view2"
        android:text="Text Line 2" />
</LinearLayout>

//場景二
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/scene_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text_view2"
        android:textSize="22sp"
        android:text="Text Line 2" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="22sp"
        android:id="@+id/text_view1"
        android:text="Text Line 1" />
</LinearLayout>

//獲取場景,開始場景間的動畫,從場景一變化爲場景二

        val sceneRoot: ViewGroup = findViewById(R.id.scene_root)
        val aScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.a_scene, this)
        val anotherScene: Scene = Scene.getSceneForLayout(sceneRoot, R.layout.another_scene, this)

        titletv.setOnClickListener {
            TransitionManager.go(anotherScene)
        }

咦,跟MotionLayout仍是蠻像的,思路也差很少,都是經過不一樣場景的控件完成過渡動畫。那麼問題來了,既然有爲何還要出個MotionLayout呢?

  • 前者(TransitionManager)沒法設置關鍵幀,動畫只有兩個狀態。 MotionLayout就能夠隨意設置關鍵幀,設置不一樣的位置,屬性等等。
  • 前者不能跟隨手勢滑動, MotionLayout就絲滑的多。
  • MotionLayout所有用 xml代碼就能夠完成整個動畫,不須要調用一句java代碼。
  • 前者佈局控件重複太多,須要不一樣的xml文件,寫 重複的控件

因此MotionLayout仍是很優秀的,快用起來吧!

附件

[官網MotionLayout案例]:https://developer.android.google.cn/training/constraint-layout/motionlayout/examples
[文章相關源代碼]:https://github.com/JiMuzz/MotionLayoutDemo


個人公衆號:碼上積木,天天三問面試題,詳細剖析,助你成爲offer收割機。

謝謝你的閱讀,若是你以爲寫的還行,就點個贊支持下吧!感謝!
你的一個👍,就是我分享的動力❤️。

今天週日上班,加更一期。國慶節就休息了哈,偷個懶,嘻嘻。

(づ ̄3 ̄)づ╭❤~


點點在看你最好看



本文分享自微信公衆號 - 碼上積木(Lzjimu)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索