Android5.0上的元素共享和CircleReveal效果

先看效果圖
gif效果圖

這個效果通過元素共享和CircleReveal共同完成,當然是有先後順序的,先執行元素共享效果,元素共享過渡效果執行完,執行CirclerReveal動畫下面介紹實現方法,代碼很少,文章最後有項目下載。

  • 共享元素
    元素共享是一個activity或fragment切換時候一個過渡效果。如果前一個界面A的元素a和後一界面B的元素b兩個元素共享,使用元素共享效果從界面A切換到界面B可以看到,a移動到b處並在移動過程中變爲b的外觀和大小;如果關閉界面B回到界面A同樣看到相反的過渡效果。所以說共享元素動畫效果取決於兩個共享元素的位置和外觀。共享元素的實現應該不是真的實現了控件元素的位移和大小外觀變化,只是的一種動畫效果。

1、使用共享元素必須滿足條件:
(1)主題需要是Theme.AppCompat下主題,才能看到共享元素效果;(2)因爲共享元素是Android5.0引入的,所以需在android5.0(LOLLIPOP)以上系統下運行,低版本運行會報錯,需加上

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){

}

2、共享元素的設置:
在代碼中設置:
view.setTransitionName( getString(R.string.transition_name));
在xml文件中設置:
android:transitionName=”@string/transition_name”
實現元素共享效果前後兩個界面的元素共享名字TransitionName必須相同,設置任意的字符串即可。
3、界面A切換到B元素共享調用方法:
創建一個ActivityOptions,通過toBundle()方法,ActivityOptions轉換成Bundle,用於startActivity傳遞bundle。ActivityOptions通過makeSceneTransitionAnimation方法在兩個activity之間產生過渡效果。
makeSceneTransitionAnimation源碼如下:

public static ActivityOptions makeSceneTransitionAnimation(
    Activity activity,View sharedElement, String sharedElementName) {
        return makeSceneTransitionAnimation(
            activity, Pair.create(sharedElement, sharedElementName));
    }

看到源碼就很好理解,參數1是當前使用共享元素的activity,參數2是共享的view,參數3是共享名,這個值不能爲null。
代碼實現,

ActivityOptions options = ActivityOptions
    .makeSceneTransitionAnimation(MainActivity.this,
    view, view.getTransitionName());
startActivityForResult(intent, 1, options.toBundle());

這樣便可實現共享動畫效果。

  • CircleReveal
    CircleReveal實現圓形縮放效果,可突出顯示某個部分。也是android5.0引入的效果,和共享元素一樣在低版本上運行會報錯。
    實現方法:
    調用ViewAnimationUtils下的createCircularReveal方法,方法返回一個Animator對象,這個Animator可以設置動畫響應屬性,調用start方法開始播放動畫,可以看出CircularReveal是一個屬性動畫,動畫設置同屬性動畫的即可。
    下面是createCircularReveal方法源碼,
/* @param view The View will be clipped to the animating circle.
* @param centerX The x coordinate of the center of the animating circle, relative to
*                <code>view</code>.
* @param centerY The y coordinate of the center of the animating circle, relative to
*                <code>view</code>.
* @param startRadius The starting radius of the animating circle.
* @param endRadius The ending radius of the animating circle.
*/
public static Animator createCircularReveal(View view,
            int centerX,  int centerY, float startRadius, float endRadius) {
        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
    }

從源碼中可以看出,參數1是執行動畫的控件,注意這個控件不是我們想突出顯示的控件,是想執行圓形展開或縮放效果的控件或佈局,參數2、3是開始執行動畫圓形的圓心的x座標和y座標,參數4是開始的半徑,參數5是結束的半徑。
瞭解傳遞參數讓我們來看看代碼部分,header是圓形縮放的中心控件,rl是RelativeLayout,是要執行動畫的佈局,header在佈局rl中。
代碼實現部分,

Animator anim = ViewAnimationUtils.createCircularReveal(
                    rl,
                    (header.getLeft() + header.getRight()) / 2,
                    (header.getTop() + header.getBottom()) / 2,
                    (float) header.getWidth() / 2,
                    finalRadius);
anim.setDuration(1000);
anim.setInterpolator(new AccelerateDecelerateInterpolator());
            anim.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                    Log.e("---", "start anim");
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    Log.e("---", "end anim");
                    //show views
                }
            });
anim.start();

finalRadius取的是圓形能覆蓋住整個rl的最小值,也就是rl這個矩形的斜角線長。

final float finalRadius = (float) Math.hypot(rl.getWidth(), rl.getHeight());

這樣CircleReveal動畫就實現了。

爲了兩個動畫平滑的連接在一起,也就是先執行activity切換的共享元元素過渡效果,再製定CircleReveal圓形展開效果,我們需要拿到元素共享效過渡效果的監聽。
在Activity B中 通過

Transition transition = getWindow().getSharedElementEnterTransition();

可以拿到Transition對象,爲transition添加監聽,可以監聽到過渡動畫結束,

transition.addListener(new Transition.TransitionListener() {
                @Override
                public void onTransitionStart(Transition transition) {

                }

                @Override//過渡結束
                public void onTransitionEnd(Transition transition) {
                    performCircleReveal();//執行CircleReveal動畫
                }

                @Override
                public void onTransitionCancel(Transition transition) {

                }

                @Override
                public void onTransitionPause(Transition transition) {

                }

                @Override
                public void onTransitionResume(Transition transition) {

                }
            });

在onTransitionEnd方法中,執行CircleReveal動畫。

這樣這個切換Activity的效果就完成了,fragment切換也可以實現元素共享效果,大家可以自行去實現。

附: 源碼地址:
http://download.csdn.net/detail/tm1989tm/9478015

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章