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

共享元素的優(yōu)點這里就不講了,很多東西學了不一定有用,但是好看的東西大家都喜歡。
注意:共享元素需要 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>
當然用 java 代碼在用到共享元素的頁面設(shè)置也可以。
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
第二步
接下來,我們需要確認兩個頁面中共享的元素。Android 提供了android:transitionName:屬性作為兩個 View 共享的標志。頁面中的共享元素可以不同id,在不同的層級,但是一定要有android:transitionName:,這是標志兩個View為共享元素的唯一標志。
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)指定頁面:
Intent intent = new Intent(MainActivity.this, TargetActivity.class);
//可添加一個或多個共享元素
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é)束頁面:
@Override
protected void onDestroy() {
supportFinishAfterTransition();
super.onDestroy();
}
效果
現(xiàn)在,你獲得的應該是這樣的動畫:

可以看到,共享元素的效果是有了,但是除了共享元素,其他的視圖卻很死板地直接顯示出來了。共享元素要想有更好的感官體驗,應該讓內(nèi)容后于共享元素顯示。因此,我們需要監(jiān)聽共享元素的動畫。
優(yōu)化
共享元素的 Transition使用的是內(nèi)部的默認值,我們無法對這個對象進行監(jiān)聽。為此,我們自定義共享元素的動畫來實現(xiàn)需要的效果。
從效果上看,默認的Transition使用的應該是ChangeBounds 。因此,我們直接使用ChangeBounds作為我們的切換動畫。
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);
//開始其他視圖的淡入動畫
}
@Override
public void onTransitionCancel(Transition transition) {
}
@Override
public void onTransitionPause(Transition transition) {
}
@Override
public void onTransitionResume(Transition transition) {
}
});
getWindow().setSharedElementReturnTransition(changeBounds);
getWindow().setSharedElementEnterTransition(changeBounds);
其他視圖的動畫,我這里就做一個簡單的淡入的例子,先在 xml 文件中把視圖 alpha 值設(shè)置為 0,然后在共享元素動畫結(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);//進入動畫
sharedElementFragment.setSharedElementEnterTransition(changeBoundsTransition);//共享元素動畫
getFragmentManager().beginTransaction()
.replace(R.id.fragment_content, sharedElementFragment)
.addToBackStack(null)
.addSharedElement(sharedView, sharedName)
.commit();
以上。
感謝: