Shared Element(共享元素)的使用

概述

當(dāng)你想要從一個(gè)頁(yè)面A轉(zhuǎn)換到頁(yè)面B共郭,而且他們共享一個(gè)元素(比如是一個(gè)view)胆胰,在這種場(chǎng)景下感昼,最好的用戶體驗(yàn)可能就是將共享的元素直接變換到最終的地方和大小坛悉,這會(huì)使用戶專(zhuān)注于應(yīng)用而且有一種連貫性的表達(dá)荷憋。這在Android5.0以上是可以很方便的實(shí)現(xiàn)的台颠,接下來(lái)就說(shuō)說(shuō)不同場(chǎng)景下ShareElements的使用。

Fragment/Activity跳轉(zhuǎn)到Activity

跳轉(zhuǎn)Activity相對(duì)簡(jiǎn)單一些勒庄,官方封裝好了使用方法:

    //這是ContextCompat里的方法串前,參數(shù)中多了一個(gè)bundle,可配置共享元素相關(guān)設(shè)置
    public static void startActivity(@NonNull Context context, @NonNull Intent intent,
            @Nullable Bundle options) {
        if (Build.VERSION.SDK_INT >= 16) {
            context.startActivity(intent, options);
        } else {
            context.startActivity(intent);
        }
    }
    //這是ActivityOptionsCompat里的方法实蔽,方便我們直接生成對(duì)應(yīng)的bundle
    @NonNull
    public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
            @NonNull View sharedElement, @NonNull String sharedElementName) {
        if (Build.VERSION.SDK_INT >= 21) {
            return createImpl(ActivityOptions.makeSceneTransitionAnimation(
                    activity, sharedElement, sharedElementName));
        }
        return new ActivityOptionsCompat();
    }

    //如果傳遞多個(gè)共享元素荡碾,則要使用到Pair
    public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
            Pair<View, String>... sharedElements)

看完support包提供的方法,來(lái)看具體使用吧:

Intent intent = new Intent(getContext(), ImageViewActivity.class);
ActivityCompat.startActivity(getContext(), intent,
           ActivityOptionsCompat.makeSceneTransitionAnimation(
                     getActivity(), ivUserInfoHead, ViewCompat.getTransitionName(ivUserInfoHead)).toBundle());

注意點(diǎn):

  1. 基本要求局装,轉(zhuǎn)場(chǎng)涉及的兩個(gè)Fragment的共享元素的transitionName要一致坛吁,可以在xml中設(shè)置,也可以通過(guò)ViewCompat.setTransitionName(view, "name")在代碼中設(shè)置铐尚。
  2. 如果使用了自定義按鈕返回拨脉,非系統(tǒng)返回,則結(jié)束Activity時(shí)不能直接finish()宣增,需要使用supportFinishAfterTransition()替代玫膀,這樣返回也會(huì)有相應(yīng)的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)了。

Fragment跳轉(zhuǎn)到Fragment

直接上代碼:

//首先在Fragment中加載一個(gè)小圖標(biāo)Fragment
getChildFragmentManager().beginTransaction()
                .replace(R.id.view_holder, new ImageViewSmallFragment())
                .commit();
//小圖標(biāo)Fragment中監(jiān)聽(tīng)點(diǎn)擊事件跳轉(zhuǎn)到大圖標(biāo)Fragment
view.findViewById(R.id.test_img).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               ImageViewFragment newFragment = new ImageViewFragment();
                //注意:這里要設(shè)置共享元素的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)爹脾,也可以把這段代碼放在newFragment的onCreate里面帖旨,看個(gè)人喜歡,我更傾向于放跳轉(zhuǎn)這里灵妨,這樣轉(zhuǎn)場(chǎng)的邏輯在一個(gè)地方碉就,更方便閱讀和理解
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    newFragment.setSharedElementEnterTransition(
                            TransitionInflater.from(getContext()).inflateTransition(android.R.transition.move));
                }
                //注意:這里要用getFragmentManager(),因?yàn)橐鎿Q掉自己
                getFragmentManager().beginTransaction()
                        //設(shè)置指定的共享元素和共享元素名字
                        .addSharedElement(view, ViewCompat.getTransitionName(view))
                        //注意:這里只能用replace闷串,用add無(wú)效
                        .replace(R.id.view_holder, newFragment)
                        //注意:這里要壓棧瓮钥,返回時(shí)才能也有轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
                        .addToBackStack("")
                        .commit();
            }
        });
//新Fragment中返回時(shí)使用popBackStack方法回退,這樣返回也能有相應(yīng)的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)了烹吵,注意碉熄,這里要使用getFragmentManager()
getFragmentManager().popBackStack();

注意點(diǎn):

  1. 基本要求,轉(zhuǎn)場(chǎng)涉及的兩個(gè)Fragment的共享元素的transitionName要一致肋拔,可以在xml中設(shè)置锈津,也可以通過(guò)ViewCompat.setTransitionName(view, "name")在代碼中設(shè)置。
  2. 跳轉(zhuǎn)新Fragment只能使用replace凉蜂,使用add無(wú)效琼梆,因?yàn)閞eplace會(huì)觸發(fā)原來(lái)Fragment生命周期的onPause性誉,而add不會(huì),所以使用add無(wú)法觸發(fā)轉(zhuǎn)場(chǎng)動(dòng)畫(huà)茎杂。
  3. 既然只能使用replace错览,則表示跳轉(zhuǎn)的Fragment和原來(lái)的Fragment要在同一個(gè)布局容器里,否則也是不會(huì)觸發(fā)原來(lái)Fragment的onPause的煌往。
  4. 是在同一個(gè)布局容器里倾哺,說(shuō)明兩個(gè)Fragment是同級(jí)的,在舊Fragment中點(diǎn)擊跳轉(zhuǎn)新Fragment時(shí)刽脖,不能使用getChildFragmentManager羞海,在Activity中就使用getSupportFragmentManager,如果是Fragment里則使用getFragmentManager()曲管。
  5. 新Fragment需要設(shè)置指定的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)却邓。
  6. 跳轉(zhuǎn)時(shí)要添加addToBackStack,這樣返回時(shí)才能正常pop院水,pop要使用getFragmentManager()申尤,返回才能有轉(zhuǎn)場(chǎng)動(dòng)畫(huà)效果。
  7. 要使用27.0.0以上的support包衙耕,因?yàn)樾碌膕upport轉(zhuǎn)場(chǎng)動(dòng)畫(huà)使用的是support包里的transition昧穿,可以參考官方support的releaseNote描述:Fragment can use support library versions of Transition for fragment transitions, including shared-element transitions.

共享元素延時(shí)加載情況

經(jīng)常會(huì)有如下場(chǎng)景,下一個(gè)頁(yè)面的共享元素需要等網(wǎng)絡(luò)接口返回后才能確定具體的位置和大小橙喘,這樣才能完成轉(zhuǎn)場(chǎng)動(dòng)畫(huà)时鸵,此時(shí),就不能直接執(zhí)行轉(zhuǎn)場(chǎng)厅瞎,需要做一些處理:

//首先在onCreate方法里暫停轉(zhuǎn)場(chǎng)
supportPostponeEnterTransition();
//然后在布局完成后饰潜,也就是合適的時(shí)機(jī)恢復(fù)轉(zhuǎn)場(chǎng)
supportStartPostponedEnterTransition();

總結(jié)

在適當(dāng)場(chǎng)景下添加轉(zhuǎn)場(chǎng)動(dòng)畫(huà),可以提高用戶體驗(yàn)和簸。但不要在一個(gè)轉(zhuǎn)場(chǎng)里添加過(guò)多的共享元素彭雾,這樣反面影響了用戶的注意點(diǎn),感覺(jué)亂锁保。官方提供的轉(zhuǎn)場(chǎng)動(dòng)畫(huà)薯酝,快點(diǎn)用到項(xiàng)目里吧~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市爽柒,隨后出現(xiàn)的幾起案子吴菠,更是在濱河造成了極大的恐慌,老刑警劉巖浩村,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件做葵,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡心墅,警方通過(guò)查閱死者的電腦和手機(jī)酿矢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)榨乎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瘫筐,你說(shuō)我怎么就攤上這事蜜暑。” “怎么了严肪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵史煎,是天一觀的道長(zhǎng)谦屑。 經(jīng)常有香客問(wèn)我驳糯,道長(zhǎng),這世上最難降的妖魔是什么氢橙? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任酝枢,我火速辦了婚禮,結(jié)果婚禮上悍手,老公的妹妹穿的比我還像新娘帘睦。我一直安慰自己,他們只是感情好坦康,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布竣付。 她就那樣靜靜地躺著,像睡著了一般滞欠。 火紅的嫁衣襯著肌膚如雪古胆。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天筛璧,我揣著相機(jī)與錄音逸绎,去河邊找鬼。 笑死夭谤,一個(gè)胖子當(dāng)著我的面吹牛棺牧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播朗儒,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼颊乘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了醉锄?” 一聲冷哼從身側(cè)響起疲牵,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榆鼠,沒(méi)想到半個(gè)月后纲爸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妆够,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年识啦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了负蚊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颓哮,死狀恐怖家妆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冕茅,我是刑警寧澤伤极,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站姨伤,受9級(jí)特大地震影響哨坪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乍楚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一当编、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧徒溪,春花似錦忿偷、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至渠概,卻和暖如春茶凳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背高氮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工慧妄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人剪芍。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓塞淹,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親罪裹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饱普,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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