五凄硼、SharedElementTransition之Activity間的轉場

1. Activity共享元素跳轉概述

shared_element.png

顯然铅协,兩個Activity之間有相同元素。

2. 實現(xiàn)Activity共享元素跳轉過程

A跳轉到B,實現(xiàn)共享元素轉場動畫只需以下幾步:

2.1 res/transition文件夾,定義界面或共享元素的轉場動畫

請看 : 三摊沉、定義 界面指定元素 或界面間共享元素 的轉場動畫基礎

2.2 在 每個 Activity 指定轉場動畫的 style ,并在Manifest 文件中 設置對應的 theme狐史。

注意,Activity Transition API 也可以使用 setSharedElementExitTransition() 和setSharedElementReenterTransition()方法分別設置共享元素的exit 和reenter 變換说墨。但是一般來講這是不必要的骏全。如果你想看先關的例子,可以查看這篇博客
this blog post ; 至于為什么Fragment中沒有共享元素的exit 和reenter 變換尼斧,請查看George Mount在stackoverflow上的回答:this StackOverflow post 姜贡。

    <style name="AppTheme.ShareElementTransition">
        <!-- 1. 開啟過渡效果,一定要-->
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowActivityTransitions">true</item>

        <item name="android:windowSharedElementEnterTransition">@transition/search_shared_enter</item>
        <item name="android:windowSharedElementReturnTransition">@transition/search_shared_return</item>
        <item name="android:windowSharedElementsUseOverlay">true</item>
    </style>

2.3 在activity B中,為需要共享的元素設置transitionName(轉場動畫中的targetId的view)

a -> b
//activity_a.xml
//這里的View可以不設置 :  android:transitionName="@string/transition_search_back"
            <ImageButton
                android:id="@+id/searchback"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="?android:selectableItemBackgroundBorderless"
                android:src="@drawable/ic_arrow_back_padded"
                />

--------------------------------------------------------------------------------------------------
//activity_b.xml ,是不是同一個view呢?還是只是Id一樣?
//回答 : 不是同一個View,id可以不一樣,因為共享只是設置動畫效果
            <ImageButton
                android:id="@+id/a"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="?android:selectableItemBackgroundBorderless"
                android:src="@drawable/ic_arrow_back_padded"
                android:transitionName="@string/transition_search_back" />

//或者
ViewCompat.setTransitionName(view,"imageView");

2.4 啟動Activity b

ActivityOptionsCompat options=ActivityOptionsCompat.makeSceneTransitionAnimation(this,view,transitionName);
ActivityCompat.startActivity(this, intent, options.toBundle());

2.5 在B中設置共享元素動畫

上面四個步驟就可以實現(xiàn)共享的動畫效果,但是!!!

Transitions并沒有把之前的View傳遞過去,本質上是兩個不同的對象,所以需要在ActivityB中為共享元素賦值棺棵÷タ龋可以在 startActivity 把數(shù)據(jù)通過intentBundle的形式傳遞,然后在ActivityB中讀取數(shù)據(jù)進行賦值....或者直接為共享的View 設置一個死值


3. 深入分析

framework的共享元素變換是通過運行時改變其屬性實現(xiàn)的,當Activity A 調用 Activity B 烛恤,發(fā)生的事件流如下:

1. Activity A調用startActivity()母怜, Activity B被創(chuàng)建,測量缚柏,同時初始化為半透明的窗口和透明的背景顏色苹熏。

2. framework重新分配每個共享元素在B中的位置與大小,使其跟A中一模一樣。之后柜裸,B的進入變換(enter transition)捕獲到共享元素在B中的初始狀態(tài)缕陕。

3. framework重新分配每個共享元素在B中的位置與大小粱锐,使其跟B中的最終狀態(tài)一致疙挺。之后,B的進入變換(enter transition)捕獲到共享元素在B中的結束狀態(tài)怜浅。

4. B的進入變換(enter transition)比較共享元素的初始和結束狀態(tài)铐然,同時基于前后狀態(tài)的區(qū)別創(chuàng)建一個Animator(屬性動畫對象)。

5. framework 命令A隱藏其共享元素恶座,動畫開始運行搀暑。隨著動畫的進行,framework 逐漸將B的activity窗口顯示出來跨琳,當動畫完成自点,B的窗口才完全可見。

與內容變換(content transition)取決于view的可見性不同(visibility)怎诫,共享元素變換取決于每個共享元素的位置酣胀、大小以及外觀赡矢。

共享元素變換并不是真正實現(xiàn)了兩個activity或者Fragment之間元素的共享,實際上我們看到的幾乎所有變換效果中(不管是B進入還是B返回A),共享元素都是在B中繪制出來的术唬。Framework沒有真正試圖將A中的某個元素傳遞給B,而是采用了不同的方法來達到相同的視覺效果滚澜。A傳遞給B的是共享元素的狀態(tài)信息粗仓。B利用這些信息來初始化共享View元素,讓它們的位置设捐、大小借浊、外觀與在A中的時候完全一致。當變換開始的時候萝招,B中除了共享元素之外蚂斤,所有的其他元素都是不可見的。隨著動畫的進行即寒,framework 逐漸將B的activity窗口顯示出來橡淆,當動畫完成,B的窗口才完全可見母赵。

3.1 監(jiān)聽動畫的變化過程,做出相對應的操作

 //當然也可以監(jiān)聽 Return,Exit,Reenter時的動畫
        getWindow().getSharedElementEnterTransition().addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {

            }

            @Override
            public void onTransitionEnd(Transition transition) {

            }

            @Override
            public void onTransitionCancel(Transition transition) {

            }

            @Override
            public void onTransitionPause(Transition transition) {

            }

            @Override
            public void onTransitionResume(Transition transition) {

            }
        });

4. 實戰(zhàn)例子

GIFsharetoAct.gif
//AndroidManifest.xml
        <activity
            android:name=".ShareElementsToActActivity"
            android:label="ShareElementsToAct"
            android:theme="@style/AppTheme.ShareElementsToAct" />

//style.xml
    <style name="AppTheme.ShareElementsToAct">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowActivityTransitions">true</item>

        <item name="android:windowSharedElementEnterTransition">@transition/enter_share_transitions</item>
        <item name="android:windowSharedElementReturnTransition">@null</item>  <!--默認和enter相反-->
    </style>

enter_share_transitions.xml

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

    <changeBounds>
        <!--patternPathMotion android:patternPathData="M0 0 L0 100 L100 0"/-->
        <targets>
            <target android:targetId="@id/iv"/>
            <target android:targetId="@id/tv"/>
        </targets>

<!--        <arcMotion
            android:maximumAngle="90"
            android:minimumHorizontalAngle="90"
            android:minimumVerticalAngle="0" />-->

    </changeBounds>

</transitionSet>

activity_share_elements_to_act.xml,注意transitionName分別為shareIvToActshareTvToAct

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.gdut.dkmfromcg.transitionlearn.ShareElementsToActActivity">

    <ImageView
        android:id="@+id/iv"
        android:src="@drawable/bangtang"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:transitionName="shareIvToAct"/>

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/iv"
        android:textSize="24dp"
        android:layout_centerHorizontal="true"
        android:transitionName="shareTvToAct"/>

</RelativeLayout>

transitionName也是為shareIvToAct 和shareTvToAct

        shareAct=findViewById(R.id.shareBetweenAct);
        shareAct.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(activity,ShareElementsToActActivity.class);
                ActivityOptionsCompat optionsCompat=ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
                        new Pair<View, String>(ivShareToAct,"shareIvToAct"),
                        new Pair<View, String>(tvShareToAct,"shareTvToAct"));

                Bundle bundle=optionsCompat.toBundle();

                /**
                 * 共享的數(shù)據(jù)仍需從這邊傳遞
                 */
                //imageView 轉換成Bitmap,可以進行傳遞,但是:Activity之間傳遞的數(shù)據(jù)量不能過大,否則程序會ORM.事實證明確實ORM了
                Bitmap bitmap=((BitmapDrawable)ivShareToAct.getDrawable()).getBitmap();
                //bundle.putParcelable("key_share_iv",bitmap); 所以這里不傳遞Bitmap
                bundle.putCharSequence("key_share_tv",tvShareToAct.getText());
                intent.putExtra("key_bundle",bundle);


                //startActivity(intent); 這樣不會產(chǎn)生共享元素的效果
                ActivityCompat.startActivity(activity,intent,bundle);
            }
        });

ShareElementsToActActivity

public class ShareElementsToActActivity extends AppCompatActivity {

    private static final String TAG = "ShareElementsToActActiv";
    ImageView imageView;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_share_elements_to_act);
        imageView=findViewById(R.id.iv);
        textView=findViewById(R.id.tv);
        Intent intent=getIntent();
        Bundle bundle=intent.getBundleExtra("key_bundle");
        Log.d(TAG, ": "+bundle);
        if (bundle!=null){
            //imageView.setImageBitmap((Bitmap) bundle.getParcelable("key_share_iv"));
            textView.setText(bundle.getCharSequence("key_share_tv"));
        }
    }
}

例子源碼:animatedTransitionsLearn-master

Transition系列文章
一逸爵、初識Transition—實現(xiàn)兩個場景的變換
二、番外篇 Transition之ViewOverlay
三凹嘲、定義 界面指定元素 或界面間共享元素 的轉場動畫基礎
四师倔、Content Transition實現(xiàn)非共享元素轉場
五、SharedElementTransition之Activity間的轉場
六周蹭、SharedElementTransition之Fragment間的轉場
七趋艘、番外篇- 自定義Visibility
八疲恢、5.0以下實現(xiàn)共享轉場


本篇參考:
深入理解共享元素變換(Shared Element Transition)-上
animatedTransitionsLearn-master
Android Transition Framework詳解---超炫的動畫框架

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瓷胧,隨后出現(xiàn)的幾起案子显拳,更是在濱河造成了極大的恐慌,老刑警劉巖搓萧,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杂数,死亡現(xiàn)場離奇詭異,居然都是意外死亡瘸洛,警方通過查閱死者的電腦和手機揍移,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來反肋,“玉大人那伐,你說我怎么就攤上這事∈幔” “怎么了罕邀?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抓督。 經(jīng)常有香客問我燃少,道長,這世上最難降的妖魔是什么铃在? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任阵具,我火速辦了婚禮,結果婚禮上定铜,老公的妹妹穿的比我還像新娘阳液。我一直安慰自己,他們只是感情好揣炕,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布帘皿。 她就那樣靜靜地躺著,像睡著了一般畸陡。 火紅的嫁衣襯著肌膚如雪鹰溜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天丁恭,我揣著相機與錄音曹动,去河邊找鬼。 笑死牲览,一個胖子當著我的面吹牛墓陈,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼贡必,長吁一口氣:“原來是場噩夢啊……” “哼兔港!你這毒婦竟也來了?” 一聲冷哼從身側響起仔拟,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤衫樊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后理逊,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體橡伞,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年晋被,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刚盈。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡羡洛,死狀恐怖,靈堂內的尸體忽然破棺而出藕漱,到底是詐尸還是另有隱情欲侮,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布肋联,位于F島的核電站威蕉,受9級特大地震影響,放射性物質發(fā)生泄漏橄仍。R本人自食惡果不足惜韧涨,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侮繁。 院中可真熱鬧虑粥,春花似錦、人聲如沸宪哩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锁孟。三九已至彬祖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間品抽,已是汗流浹背储笑。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留桑包,地道東北人南蓬。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赘方。 傳聞我的和親對象是個殘疾皇子烧颖,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容

  • 假設,兩個有Activity A和B A啟動B: A發(fā)生exit動畫窄陡,B發(fā)生enter動畫 B返回A:B發(fā)生ret...
    i冰點閱讀 17,270評論 7 42
  • 不知是經(jīng)過幾次刻意去訓練還是本章節(jié)的內容簡潔炕淮,感覺這一章看起來比較輕松。 這一章節(jié)講述了非暴力溝通的第...
    羅羅_小猴媽媽閱讀 5,125評論 0 0
  • 今天跳夭,姥爺做完透析涂圆,回家的路上就囑咐我杰哥:開車去小英家啊。前幾天就和我姨說過年時在小英家過年币叹。哈哈润歉!由于我家是一...
    快樂的櫻子閱讀 243評論 1 2
  • 經(jīng)歷了那場被小學生團滅的球賽以后,我覺得颈抚,可能我更適合一個人的運動吧踩衩,比如打臺球。 于是我打了很多年的臺球贩汉,球技日...
    一塊瘦司閱讀 188評論 0 0