
拖了很久,不過(guò)終于有時(shí)間把這個(gè)點(diǎn)給磨完了。網(wǎng)上關(guān)于共享元素的效果很多,不過(guò)大致原理相同,先看看效果圖:

共享元素的優(yōu)點(diǎn)這里就不講了,很多東西學(xué)了不一定有用,但是好看的東西大家都喜歡。
注意:共享元素需要 api 21 以上才支持
Activity 中的共享元素
第一步
首先,我們需要在style.xml中加入下面的代碼:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="android:windowContentTransitions">true</item>
...
</style>
當(dāng)然用 java 代碼在用到共享元素的頁(yè)面設(shè)置也可以。
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
第二步
接下來(lái),我們需要確認(rèn)兩個(gè)頁(yè)面中共享的元素。Android 提供了android:transitionName:屬性作為兩個(gè) View 共享的標(biāo)志。頁(yè)面中的共享元素可以不同id,在不同的層級(jí),但是一定要有android:transitionName:,這是標(biāo)志兩個(gè)View為共享元素的唯一標(biāo)志。
item_layout.xml:
<LinearLayout>
<LinearLayout>
<ImageView
android:id="@+id/item_img"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/img_1"
android:transitionName="SharedImage"
/>
<TextView/>
</LinearLayout>
</LinearLayout>
activity_target.xml
<LinearLayout>
<LinearLayout>
<TextView/>
</LinearLayout>
<LinearLayout>
<TextView/>
<ImageView
android:id="@+id/target_shareImg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:transitionName="SharedImage"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
android:src="@drawable/img_1"
/>
</LinearLayout>
</LinearLayout>
第三步
跳轉(zhuǎn)指定頁(yè)面:
Intent intent = new Intent(MainActivity.this, TargetActivity.class);
//可添加一個(gè)或多個(gè)共享元素
Pair<View, String>[] pairs = new Pair[]{
Pair.create(view.findViewById(R.id.item_img), "SharedImage")};
Pair.create(view.findViewById(R.id.item_name), "SharedName")
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(MainActivity.this, pairs);
startActivity(intent,options.toBundle());
第四步
結(jié)束頁(yè)面:
@Override
protected void onDestroy() {
supportFinishAfterTransition();
super.onDestroy();
}
效果
現(xiàn)在,你獲得的應(yīng)該是這樣的動(dòng)畫:

可以看到,共享元素的效果是有了,但是除了共享元素,其他的視圖卻很死板地直接顯示出來(lái)了。共享元素要想有更好的感官體驗(yàn),應(yīng)該讓內(nèi)容后于共享元素顯示。因此,我們需要監(jiān)聽(tīng)共享元素的動(dòng)畫。
優(yōu)化
共享元素的 Transition使用的是內(nèi)部的默認(rèn)值,我們無(wú)法對(duì)這個(gè)對(duì)象進(jìn)行監(jiān)聽(tīng)。為此,我們自定義共享元素的動(dòng)畫來(lái)實(shí)現(xiàn)需要的效果。
從效果上看,默認(rèn)的Transition使用的應(yīng)該是ChangeBounds 。因此,我們直接使用ChangeBounds作為我們的切換動(dòng)畫。
ChangeBounds changeBounds = new ChangeBounds();
changeBounds.setDuration(500);
changeBounds.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionStart(Transition transition) {
}
@Override
public void onTransitionEnd(Transition transition) {
transition.removeListener(this);
//開(kāi)始其他視圖的淡入動(dòng)畫
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
getWindow().setSharedElementReturnTransition(changeBounds);
getWindow().setSharedElementEnterTransition(changeBounds);
其他視圖的動(dòng)畫,我這里就做一個(gè)簡(jiǎn)單的淡入的例子,先在 xml 文件中把視圖 alpha 值設(shè)置為 0,然后在共享元素動(dòng)畫結(jié)束后加入這樣的代碼:
TextView textview = (TextView) findViewById(R.id.target_content);
textview.animate().setDuration(1000).alpha(1f);
我們就可以得到這樣的效果:

Fragment 中的共享元素
和 Fragment 中的 Transition 一樣,它們的屬性也都在 FragmentTransaction 中:
SharedElementFragment sharedElementFragment = SharedElementFragment.newInstance();
Slide slideTransition = new Slide(Gravity.RIGHT);
slideTransition.setDuration(500);
ChangeBounds changeBoundsTransition = new ChangeBounds();
changeBoundsTransition.setDuration(500);
sharedElementFragment.setEnterTransition(slideTransition);//進(jìn)入動(dòng)畫
sharedElementFragment.setSharedElementEnterTransition(changeBoundsTransition);//共享元素動(dòng)畫
getFragmentManager().beginTransaction()
.replace(R.id.fragment_content, sharedElementFragment)
.addToBackStack(null)
.addSharedElement(sharedView, sharedName)
.commit();
以上。
感謝: