學(xué)習(xí)收集,非原創(chuàng)
一、 簡(jiǎn)介
在Android開發(fā)過(guò)程中,經(jīng)常會(huì)碰到Activity之間的切換效果的問(wèn)題,下面介紹一下如何實(shí)現(xiàn)左右滑動(dòng)的切換效果,首先了解一下Activity切換的實(shí)現(xiàn),Android已經(jīng)內(nèi)置了幾種動(dòng)畫效果,可以見 android.R.anim 類。一般情況下我們需要自己定義屏幕切換的效果。首先我們先了解Activity的位置定義,如下圖:

從上圖可以看出,以手機(jī)屏幕下面邊未X軸,屏幕左邊為Y軸,
- 當(dāng)Activity在X軸值為-100%p時(shí),剛好在屏幕的左邊(位置1),
- 當(dāng)X軸值為0%p時(shí),剛好再屏幕內(nèi)(位置2),
- 當(dāng)X=100%p時(shí)剛好在屏幕右邊(位置3)。
清楚了位置后,我們就可以實(shí)現(xiàn)左右滑動(dòng)的切換效果,首先讓要退出的Activity從位置2移動(dòng)到位置1,同時(shí)讓進(jìn)入的Activity從位置3移動(dòng)位置2,這樣就能實(shí)現(xiàn)從左右切換效果。
實(shí)現(xiàn)過(guò)程如下,首先定義2個(gè)動(dòng)畫,在 res目錄創(chuàng)建anim目錄, 然后在目錄創(chuàng)建動(dòng)畫的xml文件:
out_to_left.xml (從左邊退出動(dòng)畫)
in_from_right.xml(從右邊進(jìn)入動(dòng)畫)
out_to_left.xml (從 位置2 移動(dòng)到 位置1)
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<translate android:fromXDelta="0%p"
android:toXDelta="-100%p"
android:duration="500" />
</set>
in_from_right.xml (從 位置3 移動(dòng)到 位置2)
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator">
<translate
android:fromXDelta="100%p"
android:toXDelta="0%p"
android:duration="500" />
</set>
二 、使用windowAnimation和ActivityAnimation設(shè)置Android轉(zhuǎn)場(chǎng)動(dòng)畫
1. windowAnimation和ActivityAnimation的區(qū)別:
顯而易見,window與Activity本身從名字上就知道不同,但對(duì)于項(xiàng)目開發(fā)中 windowAnimation和ActivityAnimation的區(qū)別必須心領(lǐng)神會(huì)。
區(qū)別主要如下:
-
windowAnimation包含:
windowEnterAnimation和windowExitAnimation
ActivityAnimation包含:android:activityOpenEnterAnimation,android:activityOpenExitAnimation,android:activityCloseEnterAnimation和android:activityCloseExitAnimation
-
windowAnimation包含:
- 在項(xiàng)目中WindowAnimation的控制權(quán)大于Activity的控制權(quán),即在Activity轉(zhuǎn)場(chǎng)過(guò)程中,如果同時(shí)設(shè)置了WindowAnimation和ActivityAnimation,那么 可能(因?yàn)檫@種情況非常多) 只會(huì)執(zhí)行WindowAnimation
- 對(duì)于WindowAnimation的定義很簡(jiǎn)單,在style.xml文件中只需要繼承Animation Style即可
2. Android使用Theme自定義Activity進(jìn)入退出動(dòng)畫
在AndroidManifest里面,對(duì)于application和activity標(biāo)簽可以定義theme屬性。如果對(duì)Application定義了某一個(gè)屬性,那么會(huì)對(duì)所有的activity產(chǎn)生影響,當(dāng)然你可以在activity中覆蓋它。
在AndroidManifestl中
對(duì)所有的activity產(chǎn)生影響
<application android:theme="@style/AppTheme">
在activity中覆蓋它
<activity
android:name=".ui.video.VideoDetailActivity"
android:label="@string/title_activity_video_detail"
android:theme="@style/AppTheme"></activity>
在values/styles.xml中
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowAnimationStyle">@style/myActivityOutEnterAnima</item>
</style>
<style name="myActivityOutEnterAnima" parent="@android:style/Animation.Activity">
<!-- 定義activity的進(jìn)出場(chǎng)動(dòng)畫 -->
<item name="android:activityOpenEnterAnimation">@anim/enter_from_right</item>
<item name="android:activityOpenExitAnimation">@anim/out_to_left</item>
<item name="android:activityCloseEnterAnimation">@anim/enter_from_left</item>
<item name="android:activityCloseExitAnimation">@anim/out_to_right</item>
</style>
在values/anim.xml中
enter_from_left.xml
enter_from_right.xml
out_to_left.xml
out_to_right.xml
android:activityOpenEnterAnimation:指的是進(jìn)入B時(shí), B的動(dòng)畫。
android:activityOpenExitAnimation:指的是進(jìn)入B時(shí),A的動(dòng)畫,與B的動(dòng)畫是一起顯示的。
android:activityCloseEnterAnimation:通過(guò)B跳轉(zhuǎn)到C后,后退到B時(shí),B的進(jìn)入動(dòng)畫
android:activityCloseExitAnimation:通過(guò)B跳轉(zhuǎn)到C后,后退到B時(shí),C的退出動(dòng)畫'
這樣就可以了,至于anim中的動(dòng)畫,就自己定義啦,這個(gè)和普通的animation是一樣的,如果不知道的話,請(qǐng)參見http://developer.android.com/guide/topics/graphics/view-animation.html。
這種方式除了可以定義activity的animation之外,還有task,window出現(xiàn)和結(jié)束時(shí)候的動(dòng)畫,具體請(qǐng)參見
http://developer.android.com/reference/android/R.styleable.html#WindowAnimation
從上述2中動(dòng)畫的定義上來(lái)看,顯然ActivityAnimation更為復(fù)雜,但這種復(fù)雜帶來(lái)的轉(zhuǎn)場(chǎng)效果非常好,可以同時(shí)控制2個(gè)Activity的動(dòng)畫,而不像WindowAnimation只能控制下一個(gè)Activity的窗體動(dòng)畫。
三、 窗體動(dòng)畫也可以使 Activity. overridePendingTransition來(lái)設(shè)置
從Android2.0開始在Activity增加了一個(gè)方法:
public void overridePendingTransition (int enterAnim, int exitAnim) 其中:
- enterAnim 定義Activity進(jìn)入屏幕時(shí)的動(dòng)畫
- exitAnim 定義Activity退出屏幕時(shí)的動(dòng)畫
注:overridePendingTransition 方法必須在startActivity()或者 finish()方法的后面。當(dāng)時(shí)沒(méi)法定義退出的動(dòng)畫
四、 5.0以后的轉(zhuǎn)場(chǎng)動(dòng)畫
1. 概述
毫無(wú)疑問(wèn),動(dòng)畫效果能提高用戶體驗(yàn)。我們平時(shí)使用最多的動(dòng)畫基本上是屬性動(dòng)畫和補(bǔ)間動(dòng)畫了,屬性動(dòng)畫很強(qiáng),基本能定制我們想要的動(dòng)畫,但是你是否知道,API 21(5.0)后系統(tǒng)內(nèi)置了Activity之間的切換動(dòng)畫,而且非常酷炫,今天我跟大家一起分享一下。
我們知道,在兩個(gè)Activity之間切換,我們一般會(huì)寫出類似下面的代碼:
在API 21以后,我們可以使用內(nèi)置的Activity切換動(dòng)畫啦。
但是這樣也就意味著只能兼容5.0之后的系統(tǒng),我們先看一個(gè)效果圖來(lái)壓壓驚:
先看看第一個(gè)Activity,退出時(shí)用的是Explode效果,第二個(gè)Activity進(jìn)入時(shí)用的是Slide效果。
這些效果無(wú)需我們自己去實(shí)現(xiàn),都是內(nèi)置的效果,我們所編寫的代碼幾乎為零,接下來(lái)我們一一看看內(nèi)置了哪些效果。
2.使用內(nèi)置Activity切換動(dòng)畫的步驟
Activity之間的切換期間,對(duì)于某個(gè)Activity來(lái)說(shuō),無(wú)非就是“進(jìn)入”和“退出”兩種情景下的動(dòng)畫。
而“進(jìn)入”分為“第一次進(jìn)入Activity”和“返回當(dāng)前Activity”這兩種情況。
另外系統(tǒng)還提供了一種動(dòng)畫,即共享元素,這是讓兩個(gè)Activity中的View有個(gè)過(guò)渡切換的效果。
執(zhí)行動(dòng)畫的狀態(tài)如下所示:
enter:用于決定第一次打開當(dāng)前Activity時(shí)的動(dòng)畫
exit : 用于決定退出當(dāng)前Activity時(shí)的動(dòng)畫
reenter: 用于決定如果當(dāng)前Activity已經(jīng)打開過(guò),并且再次打開該Activity時(shí)的動(dòng)畫
shared elements:用于決定在兩個(gè)Activity之間切換時(shí),指定兩個(gè)Activity中對(duì)應(yīng)的View的過(guò)渡效果
那么應(yīng)該怎么去使用Activity切換動(dòng)畫呢?
我們看看使用步驟:
- ** 首先在setContentView()之前執(zhí)行,用于告訴Window頁(yè)面切換需要使用動(dòng)畫接下來(lái)就是加載切換動(dòng)畫**
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
-
接下來(lái)就是加載切換動(dòng)畫
其中R.transition.explode就是要執(zhí)行的動(dòng)畫,是在res/transition目錄下的xml文件,我們使用的是系統(tǒng)內(nèi)置的Explode效果動(dòng)畫,關(guān)于怎么去寫explode.xml,我們接下來(lái)小節(jié)去講解。
-
告訴Window,當(dāng)前的Activity在什么情況下使用上面的動(dòng)畫
上面我們創(chuàng)建好了切換動(dòng)畫,接下來(lái)就是要告訴當(dāng)前窗口,在什么情況下去使用動(dòng)畫效果啦,你可以根據(jù)你的需求在不同的切換情景中選擇不同的效果:
當(dāng)然了,你也可以不使用代碼的方式,直接在你使用的主題
-
調(diào)用startActivity
跟我們之前使用的startActivity(Intent intent);不同,這里多了一個(gè)參數(shù)Bundle,我們是先通過(guò)makeSceneTransitionAnimation函數(shù)創(chuàng)建一個(gè)ActivityOptions對(duì)象,再將其轉(zhuǎn)為Bundle對(duì)象:
整體使用步驟就是以上這些,是不是很簡(jiǎn)單?接下來(lái)我們?nèi)W(xué)習(xí)如何使用內(nèi)置動(dòng)畫~
3.使用內(nèi)置動(dòng)畫
3.1 Explode效果
Explode即爆炸效果,使用Explode效果很簡(jiǎn)單,在res/transition目錄下新建一個(gè)xml文件(如explode.xml),內(nèi)容如下:
<explode
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300" />
其中duration表示Explode動(dòng)畫持續(xù)時(shí)間,由于是Activity之間的切換,最好不要把動(dòng)畫時(shí)間設(shè)置過(guò)大,一般取200~500毫秒比較合適。
我們看看效果吧~
3.2 Slide效果
即滑動(dòng)效果,使用Slide跟Explode類似,都是在res/transition目錄下新建一個(gè)xml文件(如slide.xml),內(nèi)容如下:

其中,slideEdge表示起始滑動(dòng)的側(cè)邊位置,end表示右側(cè),start表示左側(cè),top表示頂部,bottom表示底側(cè),各種效果你可以親自試試~,一起看看滑動(dòng)效果吧:
GIF 效果看的比較死板,可以下載我的源碼實(shí)際運(yùn)行一下~
如果你不希望頂部的狀態(tài)欄以及底部的導(dǎo)航欄一起執(zhí)行動(dòng)畫,可以在xml中指定:
3.3 Fade效果
Fade效果即淡化效果,使用淡化效果依然是很簡(jiǎn)單,在res/transition目錄下新建一個(gè)xml文件(如fade.xml),內(nèi)容如下:
<fade
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300" />
Fade效果就是將View逐步淡化,這里不再貼效果啦,想看效果的可以下載我的源碼運(yùn)行看看~
3.4 Shared Element效果
即共享元素效果,與前面幾種效果不同的是,共享元素效果是將前面一個(gè)Activity的某個(gè)子View與后面一個(gè)Activity的某個(gè)子View之間有過(guò)渡效果,我們先看看動(dòng)態(tài)圖感受一下:
從動(dòng)態(tài)圖中看到,第一個(gè)Activity的小綠色方塊到第二個(gè)Activity大綠色方塊有個(gè)過(guò)渡效果~
接下來(lái)我們重點(diǎn)看看如何實(shí)現(xiàn)這個(gè)效果。
如何實(shí)現(xiàn)Shared Element效果
1.將兩個(gè)Activity中需要過(guò)渡的View加上Android:transitionName屬性
兩個(gè)View的android:transitionName屬性取值要一致,比如:
第一個(gè)Activity布局:
第二個(gè)Activity布局:
兩個(gè)綠色的View都添加android:transitionName屬性,并且取名一致。
2.調(diào)用startActivity
ActivityOptions的makeSceneTransitionAnimation函數(shù)第一個(gè)參數(shù)Activity沒(méi)啥解釋的,第二個(gè)參數(shù)就是第一個(gè)Activity中的View對(duì)象,第三個(gè)參數(shù)就是兩個(gè)Activity的View的 android:transitionName屬性的值。
現(xiàn)在就可以實(shí)現(xiàn)這種Shared Element效果啦,但是可能你會(huì)想實(shí)現(xiàn)同時(shí)讓兩個(gè)View有這樣的效果,可是makeSceneTransitionAnimation函數(shù)卻只能讓我們?cè)O(shè)置一個(gè)View和一個(gè)transitionName屬性。
如何添加多個(gè)呢?
接下來(lái)我們一起學(xué)習(xí)讓多個(gè)View同時(shí)有切換效果。
除了需要將兩個(gè)Activity中需要過(guò)渡的View對(duì)應(yīng)取相同的名稱外,還需將需要過(guò)渡的View和transitionName取值對(duì)應(yīng)的String這兩個(gè)對(duì)象封裝到一個(gè)Pair對(duì)象中:
然后調(diào)用ActivityOptionsCompat類的makeSceneTransitionAnimation的另一個(gè)重載函數(shù):
makeSceneTransitionAnimation(Activity activity, Pair<View, String>... sharedElements)
第一個(gè)參數(shù)不解釋,后面參數(shù)為不定長(zhǎng)度的形參,即你可以傳遞任意多個(gè)Pair對(duì)象。

最后調(diào)用startActivity
ActivityCompat.startActivity(this, intent, transitionActivityOptions.toBundle());
說(shuō)了這么多步驟,我們來(lái)看看效果吧~
自定義 Shared Element切換動(dòng)畫
如果你對(duì)內(nèi)置的 Shared Element還不夠滿意,你還可以定制View的過(guò)渡切換效果。
步驟如下:
1.創(chuàng)建一個(gè)View的過(guò)渡移動(dòng)的軌跡路徑PathMotion類
我們可以創(chuàng)建ArcMotion對(duì)象,ArcMotion是PathMotion子類,是個(gè)曲線路徑。想要了解更多ArcMotion可以查看:
ArcMotion官方文檔
ArcMotion arcMotion = new ArcMotion();
arcMotion.setMinimumHorizontalAngle(50f);
arcMotion.setMinimumVerticalAngle(50f);
2.定義ChangeBounds類
我們自定義一個(gè)繼承ChangeBounds的類,主要重寫createAnimator函數(shù),即創(chuàng)建你要執(zhí)行的動(dòng)畫。這個(gè)函數(shù)由3個(gè)參數(shù):
ViewGroup sceneRoot:屏幕根View,即DecorView,第二個(gè)Activity的DecorView。TransitionValues startValues:屬性動(dòng)畫的起始屬性值,TransitionValues 對(duì)象內(nèi)部有各Map類型的屬性values,用于保存需要執(zhí)行屬性動(dòng)畫的屬性。這個(gè)里面的屬性值是在函數(shù)captureStartValues里放置,因此你可以重寫captureStartValues函數(shù),并把你自定義的屬性動(dòng)畫中的屬性放進(jìn)去。TransitionValues endValues:與startValues類似,表示屬性動(dòng)畫結(jié)束時(shí)的屬性值??梢酝ㄟ^(guò)重寫captureEndValues函數(shù),并把你自定義的屬性動(dòng)畫里面的最終屬性值放進(jìn)去。
我們先看一個(gè)最簡(jiǎn)單的示例:
看看效果吧~
最后5.0這部分借鑒(copy)于兩位大神,僅作為個(gè)人學(xué)習(xí)參考資料,如有侵權(quán)告知立刪除,附源圖如下
