高逼格Android轉(zhuǎn)場動畫

前言

轉(zhuǎn)場動畫在交互上非常有優(yōu)勢仰禀,本文從轉(zhuǎn)場動畫的使用場景和方法起缤谎,最后是實現(xiàn)掘金中用戶頭像的轉(zhuǎn)場動畫渗鬼。

轉(zhuǎn)場動畫適用的版本

Activity transition APIs 只有在Android 5.0(API 21)或者更高的版本上能使用刹衫。所以在使用之前需要進行版本判斷。當版本API 大于21時使用轉(zhuǎn)場動畫口糕,否則不使用缅阳。

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

還需要配置允許window content transitions 。也就是字段:android:windowActivityTransitions景描∈欤可以在activity的style文件中進行如下配置孤里。

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowActivityTransitions">true</item>
</style>

也可以在代碼中動態(tài)的配置如下:

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());

轉(zhuǎn)場動畫的使用場景

Android中的轉(zhuǎn)場動畫主要有三種場景:

1、在兩個activity之間切換時界面的過渡效果橘洞。

2捌袜、兩個activity或者Fragment之間shared elements 切換效果。

3炸枣、同一個activity中的view的動畫效果虏等。
下面分別詳細的介紹這三種方式。

1适肠、兩個activity之間切換時界面的過渡效果

兩個activity切換時的霍衫,有兩個動畫,如下圖侯养,從activity A 切換到activity B時敦跌,會有A的退出動畫和B的進入動畫。

在這里插入圖片描述

activity主要的進場和出場方法:

  • Window.setEnterTransition() 設(shè)置進場動畫
  • Window.setExitTransition() 設(shè)置出場動畫
  • Window().setReturnTransition() 設(shè)置返回activity時動畫
  • Window().setReenterTransition() 設(shè)置重新進入時動畫
    如下圖:
在這里插入圖片描述

在Google提供的android.transition.Transition包中從activity A切換到activity B有三種方式:Explode, SlideFade逛揩。
1柠傍、Explode:從屏幕的中間進入或退出。
2辩稽、Slide:從屏幕的一邊向另一邊進入或退出惧笛。
3、Fade:通過改變透明度來出現(xiàn)或消失逞泄。

效果如下圖所示:

Explode Slide Fade
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

上面的三種動畫有兩種實現(xiàn)方式:
1患整、通過xml聲明。
在res目錄下新建transition文件夾在transition文件夾下新建activity_fade.xml文件喷众。
res/transition/activity_fade.xml

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

res/transition/activity_slide.xml

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

ActivityA的代碼如下:因為從ActivityA切換到ActivityB,所以ActivityA是退出動畫使用的方法是:getWindow().setExitTransition(slide);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        setupWindowAnimations();
    }

    private void setupWindowAnimations() {
        Slide slide = TransitionInflater.from(this).inflateTransition(R.transition.activity_slide);
        getWindow().setExitTransition(slide);
    }

ActivityB是進入動畫使用方法:getWindow().setEnterTransition(fade);各谚,ActivityB的代碼如下

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        setupWindowAnimations();
    }

    private void setupWindowAnimations() {
        Fade fade = TransitionInflater.from(this).inflateTransition(R.transition.activity_fade);
        getWindow().setEnterTransition(fade);
    }

2、代碼方式實現(xiàn)到千。
ActivityA代碼如下:實現(xiàn)一個Slide對象并且設(shè)置時間為1000毫秒昌渤。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        setupWindowAnimations();
    }

    private void setupWindowAnimations() {
        Slide slide = new Slide();
        slide.setDuration(1000);
        getWindow().setExitTransition(slide);
    }

ActivityB中實現(xiàn)一個Fide對象并且設(shè)置時間為1000毫秒。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        setupWindowAnimations();
    }

    private void setupWindowAnimations() {
        Fade fade = new Fade();
        fade.setDuration(1000);
        getWindow().setEnterTransition(fade);
    }

上面兩種方式最終的實現(xiàn)效果如下:

在這里插入圖片描述

上面的動畫過程分析:
1父阻、Activity A 啟動Activity B
2愈涩、Transition FrameWork層得到Activity A的退出動畫slide并且應用到全部可見的view中望抽。
3、Transition FrameWork層得到Activity B的進入動畫fade并且應用到全部可見的view中煤篙。
4、當從Activity B返回到Activity A的時候會分別執(zhí)行Enter和Exit相反的動畫(沒有設(shè)置returnTransition苛茂,和reenterTransition時)已烤。

ReturnTransition & ReenterTransition
Return 和Reenter Transition是enter 和exit相反的過程。當從Activity A進入到Activity B時會執(zhí)行 exit和enter當從Activity B退回到Activity A時會執(zhí)行Return Transition和Reenter Transition胯究。

  • EnterTransition <--> ReturnTransition
  • ExitTransition <--> ReenterTransition
    如果沒有定義Return 或者 Reenter躁绸,那么Android會反向執(zhí)行Enter和Exit變換裕循。如下圖從Activity B退回到Activity A:


    在這里插入圖片描述

    給Activity A增加了ReturnTransition的代碼如下:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_transition);
        setupWindowAnimations();
    }

    private void setupWindowAnimations() {
        Fade fade = new Fade();
        fade.setDuration(1000);
        getWindow().setEnterTransition(fade);
        
        Slide slide = new Slide();
        slide.setDuration(1000);
        getWindow().setReturnTransition(slide);        
    }

增加了返回動畫和沒有增加返回動畫的對比效果如下:

沒有Return Transition 有return Transition
Enter:Fade In Enter:Fade In
Exit:Fade out Exit:Slide out
在這里插入圖片描述
在這里插入圖片描述

2、 Shared elements between Activities

Shared elements轉(zhuǎn)換確定兩個Activity之間共享的視圖如何在這兩個Activity之間轉(zhuǎn)換剥哑。例如淹父,如果兩個Activity在不同的位置和大小中具有相同的圖像,則通過Shared elements轉(zhuǎn)換會在這兩個Activity之間平滑地轉(zhuǎn)換和縮放圖像困介。
主要方法

在這里插入圖片描述

如下圖蘸际,當從Activity A跳轉(zhuǎn)到Activity B時,ActivityA捡鱼, ActivityB中的兩個item有動畫變化驾诈,但是要注意的時ActivityA ,ActivityB中的item是兩個獨立的item乍迄。
在這里插入圖片描述

shared elements轉(zhuǎn)換包括以下幾種:

  • changeBounds 改變目標布局中view的邊界
  • changeClipBounds 裁剪目標布局中view的邊界
  • changeTransform 實現(xiàn)旋轉(zhuǎn)或者縮放動畫
  • changeImageTransform 實現(xiàn)目標布局中ImageView的旋轉(zhuǎn)或者縮放動畫

實現(xiàn)上面的效果需要三個步驟:
1闯两、 Enable Window Content Transition
設(shè)置styles.xml文件,允許windowContentTransitions如下:
value/style.xml

<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="android:windowContentTransitions">true</item
    ...
</style>

2重慢、定義一個相同的transition名稱
分別在Activity A 和Activity B的布局文件中定義item逊躁,這兩個item的屬性可以不一樣,但是android:transitionName必須一樣核芽。如下:
layout/activity_a.xml

<ImageView
        android:id="@+id/small_blue_icon"
        style="@style/MaterialAnimations.Icon.Small"
        android:src="@drawable/circle"
        android:transitionName="@string/blue_name" />

layout/activity_b.xml

<ImageView
        android:id="@+id/big_blue_icon"
        style="@style/MaterialAnimations.Icon.Big"
        android:src="@drawable/circle"
        android:transitionName="@string/blue_name" />

3、在activity中啟動shared element
使用ActivityOptions.makeSceneTransitionAnimation()方法
ActivityA.java

blueIconImageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent i = new Intent(MainActivity.this, SharedElementActivity.class);

        View sharedView = blueIconImageView;
        String transitionName = getString(R.string.blue_name);

        ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, sharedView, transitionName);
        startActivity(i, transitionActivityOptions.toBundle());
    }
});

效果如下:

在這里插入圖片描述

Start an activity with multiple shared elements

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));

Fragment之間Shared elements

Fragment之間的Shared elements的使用過程和Activity之間的類似,分為三個步驟:
1哮独、允許windowContentTransitions

<style name="MaterialAnimations" parent="@style/Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="android:windowContentTransitions">true</item>
    ...
</style>

2、定義一個共同的變換名稱

layout/fragment_a.xml

<ImageView
        android:id="@+id/small_blue_icon"
        style="@style/MaterialAnimations.Icon.Small"
        android:src="@drawable/circle"
        android:transitionName="@string/blue_name" />

layout/fragment_b.xml

<ImageView
        android:id="@+id/big_blue_icon"
        style="@style/MaterialAnimations.Icon.Big"
        android:src="@drawable/circle"
        android:transitionName="@string/blue_name" />

3、使用FragmentTransaction

FragmentB fragmentB = FragmentB.newInstance(sample);

// Defines enter transition for all fragment views
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(1000);
sharedElementFragment2.setEnterTransition(slideTransition);

// Defines enter transition only for shared element
ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
fragmentB.setSharedElementEnterTransition(changeBoundsTransition);

getFragmentManager().beginTransaction()
        .replace(R.id.content, fragmentB)
        .addSharedElement(blueView, getString(R.string.blue_name))
        .commit();

效果如下圖

在這里插入圖片描述

設(shè)置是否允許動畫重疊
可以通過設(shè)置setAllowEnterTransitionOverlap(overlap);中的overlap的值為true或者false來允許或者不允許進場動畫和出場動畫重疊。

FragmentB fragmentB = FragmentB.newInstance(sample);

// Defines enter transition for all fragment views
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(1000);
sharedElementFragment2.setEnterTransition(slideTransition);

// Defines enter transition only for shared element
ChangeBounds changeBoundsTransition = TransitionInflater.from(this).inflateTransition(R.transition.change_bounds);
fragmentB.setSharedElementEnterTransition(changeBoundsTransition);

// Prevent transitions for overlapping
fragmentB.setAllowEnterTransitionOverlap(overlap);
fragmentB.setAllowReturnTransitionOverlap(overlap);

getFragmentManager().beginTransaction()
        .replace(R.id.content, fragmentB)
        .addSharedElement(blueView, getString(R.string.blue_name))
        .commit();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邦泄,一起剝皮案震驚了整個濱河市裂垦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌特碳,老刑警劉巖晕换,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異益愈,居然都是意外死亡夷家,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門摸袁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缺谴,“玉大人耳鸯,你說我怎么就攤上這事膀曾⊙羯叮” “怎么了?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵斩狱,是天一觀的道長所踊。 經(jīng)常有香客問我概荷,道長,這世上最難降的妖魔是什么误证? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任愈捅,我火速辦了婚禮,結(jié)果婚禮上灌具,老公的妹妹穿的比我還像新娘譬巫。我一直安慰自己,他們只是感情好缕题,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布烟零。 她就那樣靜靜地躺著,像睡著了一般锨阿。 火紅的嫁衣襯著肌膚如雪墅诡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天烟馅,我揣著相機與錄音,去河邊找鬼郑趁。 笑死,一個胖子當著我的面吹牛捆憎,可吹牛的內(nèi)容都是我干的梭纹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼础拨,長吁一口氣:“原來是場噩夢啊……” “哼瞬沦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起僚焦,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤芳悲,失蹤者是張志新(化名)和其女友劉穎边坤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茧痒,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡旺订,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拘领。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片樱调。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡届良,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出士葫,到底是詐尸還是另有隱情样漆,我是刑警寧澤晦闰,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布呻右,位于F島的核電站,受9級特大地震影響声滥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纽疟,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一憾赁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蟆肆,春花似錦晦款、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至床玻,卻和暖如春沉帮,著一層夾襖步出監(jiān)牢的瞬間贫堰,已是汗流浹背待牵。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留偎行,地道東北人贰拿。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像妙真,于是被迫代替她去往敵國和親荚守。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

推薦閱讀更多精彩內(nèi)容