您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“如何用MotionLayout實(shí)現(xiàn)王者榮耀團(tuán)戰(zhàn)效果”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
“MotionLayout 是一種布局類型,可幫助您管理應(yīng)用中的運(yùn)動(dòng)和微件動(dòng)畫。MotionLayout 是 ConstraintLayout 的子類,在其豐富的布局功能基礎(chǔ)之上構(gòu)建而成。
”
如上述介紹,MotionLayout
是 ConstraintLayout
的子類,相當(dāng)于加了動(dòng)畫功能的ConstraintLayout。MotionLayout
作為一個(gè)動(dòng)畫控件的好處就在于基本不用寫java代碼,全部在xml
文件中搞定。而且我們只需要設(shè)定起始位置,結(jié)束位置以及一些中間狀態(tài),就能自動(dòng)生成動(dòng)畫。
先分析下我們的團(tuán)戰(zhàn),主要分為三個(gè)場(chǎng)景:
瘋狂走位
的亞瑟。草叢走出
,準(zhǔn)備大戰(zhàn)。2技能
暈眩住對(duì)面的魯班七號(hào),一套技能加上鐘無(wú)艷的
大招
,將對(duì)面兩個(gè)英雄KO。包含控件:后羿,亞瑟,魯班,后羿的箭動(dòng)畫描述:走位的亞瑟,后羿射箭
首先在布局文件中,添加第一個(gè)MotionLayout
,并添加上所有的控件,后羿和魯班由于是靜止?fàn)顟B(tài),所以要寫上位置約束,其他包含動(dòng)畫的控件可以暫時(shí)不用寫位置約束:
<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
的屬性。這里可以看到有兩個(gè)新的屬性:
app:layoutDescription
,這個(gè)屬性就是代表該MotionLayout對(duì)應(yīng)的動(dòng)畫場(chǎng)景,引用的是一個(gè)
MotionScene
(XML資源文件),其中就會(huì)包括相應(yīng)布局的所有運(yùn)動(dòng)動(dòng)畫描述。app:showPaths
,這個(gè)屬性代表運(yùn)動(dòng)進(jìn)行時(shí)是否顯示運(yùn)動(dòng)路徑,也就是所有動(dòng)畫的路徑是否顯示。默認(rèn)是false。代碼中也是可以設(shè)置是否顯示動(dòng)畫路徑,
setDebugMode
方法傳入
MotionLayout.DEBUG_SHOW_PATH
屬性即可。 接下來(lái)就可以寫動(dòng)畫場(chǎng)景(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有兩個(gè)主要的標(biāo)簽Transition
和ConstraintSet
Transition
,包括運(yùn)動(dòng)的基本定義,其中
motion:constraintSetStart
和
motion:constraintSetEnd
指的是運(yùn)動(dòng)的起始狀態(tài)和結(jié)束狀態(tài)。分別就對(duì)應(yīng)下面ConstraintSet所配置的。
app:duration
代表完成運(yùn)動(dòng)所需的時(shí)間。ConstraintSet
,多個(gè)控件的端點(diǎn)約束集合,比如這里就有兩個(gè)ConstraintSet,分別代表起始約束集和結(jié)束約束集。其中Constraint
屬性指定了端點(diǎn)位置中某一個(gè)元素的位置和屬性:
ConstraintLayout
屬性。alpha,rotation,visibility,translationX,scaleX
等view基本屬性。CustomAttribute
表示,舉個(gè)小栗子: <Constraint
android:id="@+id/button" ...>
<CustomAttribute
motion:attributeName="backgroundColor"
motion:customColorValue="#D81B60"/>
</Constraint>
attributeName屬性就是與具有getter
和setter
方法的對(duì)象匹配,比如這里的backgroundColor
就對(duì)應(yīng)了view本身的基本方法getBackgroundColor()
和 setBackgroundColor()
。
好了
,回到后裔這邊,由于后羿的箭是從后羿位置到亞瑟位置,所以我們?cè)O(shè)定好后羿箭的兩個(gè)端點(diǎn)狀態(tài),配置好后,MotionLayout
就會(huì)自動(dòng)幫我們生成從起始狀態(tài)到結(jié)束狀態(tài)的動(dòng)畫了,后羿箭從后羿位置飛到了亞瑟位置。等等,運(yùn)行怎么沒(méi)反應(yīng)呢?動(dòng)畫怎么觸發(fā)???
Motion提供了三動(dòng)畫觸發(fā)方法:1)onClick標(biāo)簽,表示點(diǎn)擊場(chǎng)景中的某個(gè)控件來(lái)觸發(fā)動(dòng)畫效果。其中有兩個(gè)屬性。
app:targetId
,表示要觸發(fā)動(dòng)畫的視圖app:clickAction
,表示點(diǎn)擊的效果,例如,toggle(循環(huán)動(dòng)畫),transitionToStart(過(guò)渡到開(kāi)始狀態(tài))2)OnSwipe標(biāo)簽,表示通過(guò)用戶輕觸控制動(dòng)畫,有點(diǎn)手勢(shì)滑動(dòng)的感覺(jué)
app:touchAnchorId
,表示可以滑動(dòng)并拖動(dòng)的視圖。app:touchAnchorSide
表示從哪邊開(kāi)始拖動(dòng)。app:dragDirection
表示拖動(dòng)的進(jìn)度方向。例如,dragRight表示當(dāng)向右拖動(dòng)(滑動(dòng))。app:onTouchUp
表示手勢(shì)抬起的時(shí)候動(dòng)作。例如,stop表示手勢(shì)抬起的時(shí)候view動(dòng)畫停止。3)java代碼控制.
motionLayout.transitionToEnd()
,過(guò)渡動(dòng)畫到結(jié)束位置。motionLayout.setTransitionListener
,監(jiān)聽(tīng)動(dòng)畫。這里我們就設(shè)置點(diǎn)擊后羿觸發(fā)動(dòng)畫:
<OnClick
app:clickAction="toggle"
app:targetId="@id/houyi" />
好了,運(yùn)行,點(diǎn)擊后羿,后羿的箭成功射出去了。
但是這還不夠,后羿箭到亞瑟位置肯定就會(huì)消失了,怎么表示這個(gè)消失呢?用透明度
,直接設(shè)置結(jié)束位置的透明度為0就會(huì)消失了。
android:alpha="0"
看看效果:
好像還是有點(diǎn)不對(duì),箭在空中的時(shí)候就消失了,我們要的效果是射到亞瑟才消失
。這是因?yàn)樯蓜?dòng)畫的時(shí)候是按照起始點(diǎn)到結(jié)束點(diǎn)過(guò)渡的流程平均分配到每個(gè)時(shí)間點(diǎn),所以他就會(huì)從一開(kāi)始就慢慢線性變化透明度,直到完全消失。
怎么辦呢?就要用到關(guān)鍵幀KeyFrameSet
了。
KeyFrameSet
關(guān)鍵幀,可以設(shè)定動(dòng)畫過(guò)程中的某個(gè)關(guān)鍵位置或?qū)傩?。設(shè)定關(guān)鍵幀后,MotionLayout
會(huì)平滑地將視圖從起點(diǎn)移至每個(gè)中間點(diǎn),然后移至最終目標(biāo)位置。所以這里,我們需要設(shè)置兩個(gè)關(guān)鍵屬性
, 1)快射到亞瑟的時(shí)候,箭的透明度還是1。2)射到亞瑟的時(shí)候,透明度改成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就是設(shè)置關(guān)鍵屬性的標(biāo)簽,其中
app:framePosition
表示該關(guān)鍵幀的位置,相當(dāng)于百分比。app:motionTarget
表示作用于那個(gè)視圖這樣設(shè)置好,后羿箭的動(dòng)畫也就完成了。
到亞瑟了,亞瑟的動(dòng)畫效果是走位走位被射中。所以先設(shè)定好亞瑟的位置,從遠(yuǎn)處走到被射中的位置。
<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>
可以看到,一個(gè)端點(diǎn)狀態(tài),可以放置多個(gè)控件屬性。
放好亞瑟的起始和結(jié)束狀態(tài)后,再設(shè)定瘋狂走位,怎么弄?——KeyCycle
KeyCycle
,循環(huán)關(guān)鍵幀,可以給動(dòng)畫添加振動(dòng),其實(shí)就是波形圖,比如sin,cos
。這里我們就設(shè)定一個(gè)sin曲線給亞瑟,作為走位的路徑。也是放到關(guān)鍵幀KeyFrameSet
標(biāo)簽下。
<KeyCycle
android:translationY="50dp"
app:framePosition="70"
app:motionTarget="@id/yase"
app:wavePeriod="0.5"
app:waveShape="sin" />
app:waveShape
表示波動(dòng)類型,比如sin,cosapp:wavePeriod
表示波動(dòng)周期,比如0.5就表示半個(gè)sin周期,可以理解為震動(dòng)0.5次。好了,第一個(gè)場(chǎng)景搞定,看看效果:
包含控件:妲己,鐘無(wú)艷動(dòng)畫描述:從草叢走出來(lái)的妲己和鐘無(wú)艷
這一個(gè)場(chǎng)景主要是描述在草叢蹲伏
的妲己和鐘無(wú)艷,看到后羿射箭后,走出草叢準(zhǔn)備接技能
。直接上代碼:
<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>
這里,我想給鐘無(wú)艷一個(gè)異形走位
,就是先在草叢里走,再出來(lái)。這時(shí)候就要用到另一個(gè)關(guān)鍵幀標(biāo)簽——KeyPosition
KeyPosition,表示關(guān)鍵幀的位置,也就是動(dòng)畫必經(jīng)的一個(gè)點(diǎn)。該屬性用于調(diào)整默認(rèn)的運(yùn)動(dòng)路徑。
1) motion:percentX、motion:percentY指定視圖應(yīng)到達(dá)的位置。keyPositionType 屬性指定如何解釋這些值。
2) keyPositionType有三種設(shè)置
parentRelative
,相對(duì)于父視圖的位置,x為橫軸(0左-1右),y為縱軸(0頂-1底)比如要設(shè)置位置到右端中部位置,就設(shè)定app:percentY="0.5" app:percentX="1"即可。deltaRelative
,相對(duì)于視圖在整個(gè)運(yùn)動(dòng)序列過(guò)程中移動(dòng)的距離,(0,0)為視圖起始位置,(1,1)為結(jié)束位置。x為橫軸,y為縱軸pathRelative
,x軸方向?yàn)橐晥D在路徑范圍內(nèi)移動(dòng)的方向,0位視圖起始位置,1為結(jié)束位置(即x軸為起點(diǎn)和終點(diǎn)的連接線)。y軸垂直于x軸,正值為路徑左側(cè),負(fù)值為右側(cè)。所以,這個(gè)和deltaRelative相比,就是x軸和Y軸的不同,相同的是都是按照起始位置到結(jié)束位置為參考。這里我們給鐘無(wú)艷一個(gè)parentRelative。
<KeyPosition
app:motionTarget="@id/zhongwuyan"
app:framePosition="30"
app:keyPositionType="parentRelative"
app:percentY="0"
app:percentX="0.4"
/>
最后加上兩個(gè)英雄從草叢走出來(lái),由半透明到不透明的過(guò)程:
<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" />
包含控件:妲己的一技能,妲己的二技能,鐘無(wú)艷動(dòng)畫描述:鐘無(wú)艷閃現(xiàn)到人群中使用大招轉(zhuǎn)轉(zhuǎn)轉(zhuǎn),妲己二技能暈眩住魯班,一技能跟上。
鐘無(wú)艷閃現(xiàn),我用的是消失再出現(xiàn)的方式,也就是改變alpha
。鐘無(wú)艷的大招,用到的是android:rotationY
,設(shè)定繞y軸旋轉(zhuǎn)。
妲己的一技能和二技能都是用的普通位置移動(dòng),注意控制透明度也就是出現(xiàn)和消失即可。上代碼:
//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>
<!-- 鐘無(wú)艷-->
<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>
其實(shí)做下來(lái)可以發(fā)現(xiàn),Motionlayout
實(shí)現(xiàn)動(dòng)畫真的很簡(jiǎn)便,大大提高了開(kāi)發(fā)效率,這也是jetpack
組件開(kāi)發(fā)的初心。但是,Motionlayout
還是有缺點(diǎn)的,比如直接通過(guò)xml代碼的情況下,無(wú)法設(shè)置動(dòng)畫的銜接,設(shè)定動(dòng)畫的先后順序。所以到底motionlayout
應(yīng)用場(chǎng)景是什么呢?
motionlayout
作為一個(gè)過(guò)渡動(dòng)畫,應(yīng)該適用于一些控件切換,界面變化之類的動(dòng)畫。比如DrawerLayout,viewpager
切換的時(shí)候,可以設(shè)置一些view過(guò)渡的動(dòng)畫。官網(wǎng)有一個(gè)類似youtube
中運(yùn)動(dòng)動(dòng)畫的案例,我這邊搬過(guò)來(lái)簡(jiǎn)單說(shuō)下。先看看效果
效果不錯(cuò)吧,特別是手勢(shì)滑動(dòng)的那個(gè)絲滑感
,太爽了,以前做這種動(dòng)畫效果少說(shuō)也要半個(gè)小時(shí)吧,想想就頭疼。現(xiàn)在,MotionLayout:so easy。
來(lái)一起分析下:
包含控件:頂部布局控件topLayout
(包含頂部圖片topImage,播放按鈕topPlay,關(guān)閉按鈕topClose),中部布局midlayout
(包含文字部分midView),下部菜單控件bottomView
動(dòng)畫描述(某些具體數(shù)值由代碼中得知):
topLayout
從上方依附parent位置,變化到下方bottomView的上方。高度由320dp變成54dp。topImage
從滿鋪父布局,到最后長(zhǎng)度不滿鋪(長(zhǎng)度設(shè)置為高度2.5倍),高度距離父布局上下2dp。關(guān)鍵幀:到90%進(jìn)度的時(shí)候,還是滿鋪,再慢慢縮小長(zhǎng)度。topPlay
,topClose從不顯示(alhpa為0)到最后顯示完全(alhpa為1)。關(guān)鍵幀:到90%進(jìn)度的時(shí)候,不透明還是為10%(alpha0.1),再慢慢變不透明。midlayout
,白色布局,從底部依附父布局到bottomView的上方,這個(gè)layout是為了讓toplayout下來(lái)的時(shí)候更加自然,因?yàn)閞ecycleview會(huì)變完全透明,就需要這個(gè)白色布局過(guò)渡,讓動(dòng)畫更完整。midView
,從toplayout下方位置到最后和toplayout重合,透明度從不透明到完全透明。關(guān)鍵幀:到75%進(jìn)度的時(shí)候,就完全透明。bottomView
,從父布局視圖下面(看不到)到父布局底部(看得見(jiàn))就這么多,分析好每個(gè)布局的起始位置,結(jié)束位置,再調(diào)整一下關(guān)鍵幀。一個(gè)跟隨手勢(shì)滑動(dòng)的過(guò)渡動(dòng)畫布局就完成了。貼下MotionScene
關(guān)鍵代碼,想看完整源代碼可以去文末附件自取,官網(wǎng)案例和我的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>
這里有幾個(gè)新屬性說(shuō)下:
motion:curveFit
,表示用哪種線條軌跡經(jīng)過(guò)該關(guān)鍵幀,默認(rèn)是曲線(spline),更加圓滑。這是設(shè)置的linear為直線過(guò)渡,因?yàn)楸旧砭褪侵本€,所以沒(méi)什么影響。motion:percentWidth
,表示視圖相對(duì)大小,取值為0-1,0代表初始位置寬度,1代表結(jié)束位置寬度。這里為0就代表寬度到該位置還是和初始寬度一致。motion:motionInterpolator
,表示動(dòng)畫的插值器。這里的linear就是線性運(yùn)動(dòng),還可以設(shè)置bounce彈簧運(yùn)動(dòng)等等。關(guān)于過(guò)渡動(dòng)畫,其實(shí)之前也是存在的——TransitionManager
。TransitionManager
可以提供不同場(chǎng)景之間的過(guò)渡轉(zhuǎn)換動(dòng)畫,需要設(shè)定兩個(gè)場(chǎng)景(布局文件),然后兩個(gè)場(chǎng)景中對(duì)應(yīng)的控件id要對(duì)應(yīng)上。最后通過(guò)java代碼執(zhí)行過(guò)渡動(dòng)畫。
上個(gè)代碼:
//兩個(gè)場(chǎng)景的布局
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/scene_root">
<include layout="@layout/a_scene" />
</FrameLayout>
//場(chǎng)景一
<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>
//場(chǎng)景二
<?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>
//獲取場(chǎng)景,開(kāi)始場(chǎng)景間的動(dòng)畫,從場(chǎng)景一變化為場(chǎng)景二
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
還是蠻像的,思路也差不多,都是通過(guò)不同場(chǎng)景的控件完成過(guò)渡動(dòng)畫。那么問(wèn)題來(lái)了,既然有為什么還要出個(gè)MotionLayout呢?
MotionLayout
就可以隨意設(shè)置關(guān)鍵幀,設(shè)置不同的位置,屬性等等。MotionLayout
就絲滑的多。xml代碼
就可以完成整個(gè)動(dòng)畫,不需要調(diào)用一句java代碼。重復(fù)的控件
。“如何用MotionLayout實(shí)現(xiàn)王者榮耀團(tuán)戰(zhàn)效果”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。