Android動(dòng)畫之場景變換Transition動(dòng)畫的使用

Transition 概述

Trasition 內(nèi)部保存了所有關(guān)于動(dòng)畫的信息,當(dāng)場景變換時(shí)動(dòng)畫將在目標(biāo)對象上執(zhí)行。Transition基于兩個(gè)概念:場景(scenes)和變換(transitions),場景是UI當(dāng)前狀態(tài),變換則定義了在不同場景之間動(dòng)畫變化的過程。

Transition分為三種類型(android5.0中使用)。
進(jìn)入動(dòng)畫:Activity中的所有視圖進(jìn)入屏幕的動(dòng)畫。
退出動(dòng)畫:Activity中的所有視圖退出屏幕的動(dòng)畫。
共享元素動(dòng)畫:利用共享的元素實(shí)現(xiàn)Activity的跳轉(zhuǎn)動(dòng)畫。
進(jìn)入動(dòng)畫和退出動(dòng)畫合稱Content Transition(內(nèi)容變換動(dòng)畫),所以Transition分為內(nèi)容變換動(dòng)畫和共享元素動(dòng)畫。

當(dāng)一個(gè)場景改變的時(shí)候,transition主要負(fù)責(zé):
捕捉每個(gè)View在開始場景和結(jié)束場景時(shí)的狀態(tài),根據(jù)兩個(gè)場景(開始和結(jié)束)之間的區(qū)別創(chuàng)建一個(gè)Animator,所以Transition內(nèi)部利用了屬性動(dòng)畫。

如何在Activity中使用Transition

  • 在使用Transition 的activity中需要啟用transition ,可以通過代碼也可以通過設(shè)置主題:

代碼方式,在setContentView之前調(diào)用:
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
主題xml方式:

<item name="android:windowContentTransitions">true</item>
  • Activity中設(shè)置進(jìn)入,退出Transition動(dòng)畫,Material主題默認(rèn)會將exit的transition設(shè)置成null而enter的transition設(shè)置成Fade ,如果reenter 或者 return transition沒有明確設(shè)置,則將用exit 和enter的transition替代。

  • 開始一個(gè)activity的content transition需要調(diào)用startActivity(Context, Bundle)方法,Bundle參數(shù)生成方法ActivityOptions.makeSceneTransitionAnimation(activity, pairs).toBundle();

  • 在代碼中觸發(fā)通過finishAfterTransition()方法觸發(fā)返回動(dòng)畫,而不是調(diào)用finish()方法。

Fragment中使用Transition

和activity中使用大體相同,不同點(diǎn)如下:

  • Fragment在其FragmentTransaction執(zhí)行added, removed, attached, detached, shown, ,hidden時(shí)觸發(fā)動(dòng)畫。

  • 在Fragment commit之前,共享元素需要通過調(diào)用addSharedElement(View, String) 方法來成為FragmentTransaction的一部分。

2 Content Transition

content transition決定了非共享view元素在activity和fragment切換期間是如何進(jìn)入或者退出場景的
可以利用代碼或者XML方式實(shí)現(xiàn)。

設(shè)置Content Transition的函數(shù):
setEnterTransition() - ActivityA 跳轉(zhuǎn)到 ActivityB,ActivityB中的View進(jìn)入場景的transition。
setExitTransition() - ActivityA 跳轉(zhuǎn)到 ActivityB,ActivityA中的View退出場景的transition。
setReturnTransition() - 從ActivityB 返回Activity A時(shí),ActivityB中的View退出場景的transition。
setReenterTransition() - 從ActivityB 返回Activity A時(shí),ActivityA中的View進(jìn)入場景的transition

xml中的屬性

//對應(yīng)setEnterTransition
<item name="android:windowEnterTransition"></item>   
//對應(yīng)setExitTransition
<item name="android:windowExitTransition"></item>
//對應(yīng)setReturnTransition
<item name="android:windowReturnTransition"></item>
//對應(yīng)setReenterTransition
<item name="android:windowReenterTransition"></item>

系統(tǒng)提供的動(dòng)畫效果(用于content Transition)
explode(分解):從屏幕中間進(jìn)或出,移動(dòng)視圖。
slide(滑動(dòng)):從屏幕邊緣進(jìn)或出,移動(dòng)試圖。
fade(淡出):通過改變屏幕上的視圖的不透明度,達(dá)到添加或移除視圖。

三種效果都有對應(yīng)的實(shí)現(xiàn)類,分別為:
分解:Explode
Xml中定義方式:<explode xmlns:android="http://schemas.android.com/apk/res/android"/>

滑動(dòng):Slide,
setSlideEdge(int slideEdge) 設(shè)置從哪個(gè)邊出現(xiàn)或隱藏,取值為
Gravity.LEFT, Gravity.TOP, Gravity.RIGHT, Gravity.BOTTOM, Gravity.START, Gravity.END.
對應(yīng)的xml中的屬性為android:slideEdge
Xml中定義slide方式:

<slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="bottom"/>

淡入淡出對應(yīng)Fade:
Xml中使用方式:<fade xmlns:android="http://schemas.android.com/apk/res/android"/>

XML方式定義transition

explode

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<explode
    android:duration="500"
    android:interpolator="@android:interpolator/accelerate_decelerate"/>
</transitionSet>

fade

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
<fade
    android:duration="500"
    android:interpolator="@android:interpolator/accelerate_decelerate"/>
</transitionSet>

slide

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <slide
        android:duration="500"
        android:slideEdge="bottom"
        android:interpolator="@android:interpolator/accelerate_decelerate" />
</transitionSet>

xml中實(shí)現(xiàn)進(jìn)入退出動(dòng)畫

Style中設(shè)置:

<item name="android:windowContentTransitions">true</item>
        <item name="android:windowEnterTransition">@transition/explode</item>
        <item name="android:windowExitTransition">@transition/fade</item>
        <item name="android:windowReenterTransition">@transition/solid</item>
        <item name="android:windowReturnTransition">@transition/explode</item>

調(diào)用

ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(Main8Activity.this);
Intent intent = new Intent(Main8Activity.this, Main7Activity.class);
startActivity(intent,activityOptionsCompat.toBundle());

退出時(shí)調(diào)用:

@Override
public void onBackPressed() {
    super.onBackPressed();
    ActivityCompat.finishAfterTransition(this);
}

代碼方式實(shí)現(xiàn)

oncreate函數(shù)中

@Override
protected void onCreate(Bundle savedInstanceState) {
   // overridePendingTransition(R.anim.translate_left_in,0);
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    getWindow().setEnterTransition(new Explode());
    getWindow().setExitTransition(new Fade());
    Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.slide_bottom);
    getWindow().setReenterTransition(transition1);
    Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.explode);
    getWindow().setReturnTransition(transition2);
    //super.onCreate之前
    super.onCreate(savedInstanceState);

退出時(shí)調(diào)用:

@Override
public void onBackPressed() {
    super.onBackPressed();
    ActivityCompat.finishAfterTransition(this);
}

explode,fade,solid效果

explode效果

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Explode());
getWindow().setExitTransition(new Explode());
Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.explode);
getWindow().setReenterTransition(transition1);
Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.explode);
getWindow().setReturnTransition(transition2);

圖片3

fade效果

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Fade());
getWindow().setExitTransition(new Fade());
Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.fade);
getWindow().setReenterTransition(transition1);
Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.fade);
getWindow().setReturnTransition(transition2);
圖片4

solid

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
getWindow().setEnterTransition(new Slide(Gravity.BOTTOM));
getWindow().setExitTransition(new Slide(Gravity.TOP));
Transition transition1 =  TransitionInflater.from(Main8Activity.this).inflateTransition(R.transition.solid);
getWindow().setReenterTransition(transition1);
Transition transition2 =  TransitionInflater.from(Main8Activity.this).inflateTransition(android.R.transition.slide_bottom);
getWindow().setReturnTransition(transition2);

圖片5

]
PS:
如果從ActivityA啟動(dòng)ActivityB,界面切換的時(shí)候,ActivityA退出還沒有完全展示exitAnimator時(shí),ActivityB就進(jìn)入了,如果想等ActivityA完全退出后ActivityB再進(jìn)入可以通過設(shè)置setAllowEnterTransitionOverlap(false)(默認(rèn)是true),同樣可以在xml中設(shè)置:
<item name="android:windowAllowEnterTransitionOverlap">false</item>
<item name="android:windowAllowReturnTransitionOverlap">false</item>

3 共享元素動(dòng)畫

函數(shù)說明:
setSharedElementEnterTransition();ActivityA 跳轉(zhuǎn)到 ActivityB,ActivityB進(jìn)入動(dòng)畫transitionsetSharedElementExitTransition();ActivityA 跳轉(zhuǎn)到 ActivityB,ActivityA退出動(dòng)畫setSharedElementReenterTransition();從ActivityB 返回Activity A時(shí),ActivityA進(jìn)入場景的transition。
setSharedElementReturnTransition();從ActivityB 返回Activity A時(shí),ActivityB退出場景的transition。

xml中對應(yīng)的設(shè)置

<item name="android:windowSharedElementEnterTransition"></item>
<item name="android:windowSharedElementExitTransition"></item>
<item name="android:windowSharedElementReenterTransition"></item>
<item name="android:windowSharedElementReturnTransition"></item>

系統(tǒng)提供的自定義動(dòng)畫
changeBounds:改變目標(biāo)視圖的布局邊界,也就是改變view的寬高或者位置。
changeClipBounds:裁剪目標(biāo)視圖邊界,view的裁剪區(qū)域邊界。
changeTransform:改變目標(biāo)的縮放比例和旋轉(zhuǎn)角度,對view進(jìn)行縮放,旋轉(zhuǎn)操作。
changeImageTransform:改變目標(biāo)圖片的大小和縮放比例,也就是改變圖片的ScaleType。
overlay:覆蓋
arcMotion:圓弧效果

對應(yīng)的類:
ChangeBounds -捕獲共享元素的layout bound,然后播放layout bound變化動(dòng)畫。ChangeBounds 是共享元素變換中用的最多的,因?yàn)榍昂髢蓚€(gè)activity中共享元素的大小和位置一般都是不同的。
ChangeTransform - 捕獲共享元素的縮放(scale)與旋轉(zhuǎn)(rotation)屬性 ,然后播放縮放(scale)與旋轉(zhuǎn)(rotation)屬性變化動(dòng)畫。
ChangeClipBounds - 捕獲共享元素clip bounds,然后播放clip bounds變化動(dòng)畫,view的裁剪區(qū)域邊界。
ChangeImageTransform - 捕獲共享元素(ImageView)的transform matrices 屬性,然后播放ImageViewtransform matrices 屬性變化動(dòng)畫。與ChangeBounds相結(jié)合,這個(gè)變換可以讓ImageView在動(dòng)畫中高效實(shí)現(xiàn)大小,形狀或者ImageView.ScaleType 屬性平滑過度。

getWindow().setSharedElementsUseOverlay(true); overlay效果開啟

定義xml文件
changeBounds

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeBounds
        android:duration="1000"
        android:interpolator="@android:interpolator/accelerate_decelerate" />
</transitionSet>

changeClipBounds

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeClipBounds
        android:duration="1000"
        android:interpolator="@android:interpolator/accelerate_decelerate" />
</transitionSet>

changeImageTransform

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeImageTransform
        android:duration="500"
        android:interpolator="@android:interpolator/accelerate_decelerate" />
</transitionSet>

changeTransform

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
    <changeTransform
        android:duration="500"
        android:interpolator="@android:interpolator/accelerate_decelerate" />
</transitionSet>

style中設(shè)置

<item name="android:windowContentTransitions">true</item>
<item name="android:windowSharedElementEnterTransition">@transition/changebounds</item>
<item name="android:windowSharedElementExitTransition">@transition/changeclipbounds</item>
<item name="android:windowSharedElementReenterTransition">@transition/changeimagetransform</item>
<item name="android:windowSharedElementReturnTransition">@transition/changetransform</item>
 Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(Main8Activity.this,gongxiang,"shareElement").toBundle();
 Intent intent = new Intent(Main8Activity.this, Main7Activity.class);
 startActivity(intent,bundle);
<ImageView
    android:id="@+id/gongxiang"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="400px"
    android:src="@drawable/image_home_game_nor2"
    android:transitionName="shareElement"/>
<ImageView
    android:id="@+id/toptop"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/image_home_game_nor"
    android:scaleType="fitCenter"
    android:transitionName="shareElement"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintRight_toRightOf="parent" />

Main8Activity和Main7Activity 共享兩個(gè)圓形imageView:

代碼實(shí)現(xiàn)

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(1000);
ChangeClipBounds changeClipBounds = new ChangeClipBounds();
changeClipBounds.setDuration(1000);
ChangeImageTransform changeImageTransform = new ChangeImageTransform();
changeImageTransform.setDuration(1000);
ChangeTransform changeTransform = new ChangeTransform();
changeTransform.setDuration(1000);
getWindow().setSharedElementEnterTransition(changeBounds);
getWindow().setSharedElementExitTransition(changeClipBounds);
getWindow().setSharedElementReenterTransition(changeImageTransform);
getWindow().setSharedElementReturnTransition(changeTransform);

開啟Overlay

Overlay的具體效果不太明白,但是從語義來說應(yīng)該是讓動(dòng)畫更加的融合自然。
getWindow().setSharedElementsUseOverlay(true);


image

參考:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0201/2394.html

Animation動(dòng)畫概述和執(zhí)行原理
Android動(dòng)畫之補(bǔ)間動(dòng)畫TweenAnimation
Android動(dòng)畫之逐幀動(dòng)畫FrameAnimation
Android動(dòng)畫之插值器簡介和系統(tǒng)默認(rèn)插值器
Android動(dòng)畫之插值器Interpolator自定義
Android動(dòng)畫之視圖動(dòng)畫的缺點(diǎn)和屬性動(dòng)畫的引入
Android動(dòng)畫之ValueAnimator用法和自定義估值器
Android動(dòng)畫之ObjectAnimator實(shí)現(xiàn)補(bǔ)間動(dòng)畫和ObjectAnimator自定義屬性
Android動(dòng)畫之ObjectAnimator中ofXX函數(shù)全解析-自定義Property,TypeConverter,TypeEvaluator
Android動(dòng)畫之AnimatorSet聯(lián)合動(dòng)畫用法
Android動(dòng)畫之LayoutTransition布局動(dòng)畫
Android動(dòng)畫之共享元素動(dòng)畫
Android動(dòng)畫之ViewPropertyAnimator(專用于view的屬性動(dòng)畫)
Android動(dòng)畫之Activity切換動(dòng)畫overridePendingTransition實(shí)現(xiàn)和Theme Xml方式實(shí)現(xiàn)
Android動(dòng)畫之ActivityOptionsCompat概述
Android動(dòng)畫之場景變換Transition動(dòng)畫的使用
Android動(dòng)畫之Transition和TransitionManager使用
Android動(dòng)畫之圓形揭露動(dòng)畫Circular Reveal
Android 動(dòng)畫之 LayoutAnimation 動(dòng)畫
Android動(dòng)畫之視圖動(dòng)畫的缺點(diǎn)和屬性動(dòng)畫的引入

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容