Andorid Transitions Framework(過(guò)渡動(dòng)畫(huà))

Material-Animaltion

英文原文 https://github.com/lgvalle/Material-Animations

這是GitHub上的一個(gè)開(kāi)源項(xiàng)目(點(diǎn)擊傳送門(mén)), 演示View的平移蛮粮、縮放動(dòng)畫(huà)松却,activity進(jìn)入和退出動(dòng)畫(huà)翅楼,界面間元素共享理澎。

Andorid Transitions Framework

了解 Transition Framework

作用

  • 可以在activity之間跳轉(zhuǎn)的時(shí)候添加動(dòng)畫(huà)

  • 動(dòng)畫(huà)共享元素之間的轉(zhuǎn)換活動(dòng)

  • activity中布局元素的過(guò)渡動(dòng)畫(huà)酥宴。

1. Transitions between Activitys

  • Animate existing activity layout content
image
image

當(dāng)過(guò)渡從activity到activity內(nèi)容布局是根據(jù)定義的過(guò)渡動(dòng)畫(huà)弯淘。有三個(gè)預(yù)定義的轉(zhuǎn)換android.transition上可用榆综。轉(zhuǎn)換可以使用:Explode,Slide和Fade妙痹。所有這些轉(zhuǎn)換跟蹤更改目標(biāo)的可見(jiàn)性活動(dòng)視圖布局和動(dòng)畫(huà)那些觀點(diǎn)遵循轉(zhuǎn)換規(guī)則。

Explode Slide Fade
image
image
image
image

實(shí)現(xiàn)這些效果可以通過(guò)xml方式或者在直接在類中實(shí)現(xiàn),下面是Fade的實(shí)現(xiàn)方式鼻疮。

說(shuō)明:Fade

  1. 如果是xml方式實(shí)現(xiàn)怯伊,首先在/res下創(chuàng)建transition文件夾。

res/transition/slide_from_right

<?xml version = 1.0 encoding = "utf-8"?>
<transitionSet xmls:android = "http://schemas.android.com/apk/res/android">

<slide duration = "500"
       slideEage = "left"/>
       
</transitionSet>

2.如果直接用代碼實(shí)現(xiàn)陋守,可以如下實(shí)現(xiàn)

MainActivity

Slide slideTracition = newSlide();

slideTracition.setSlideEdge(Gravity.LEFT);

slideTracition.setDuration(getResources().getInteger(R.integer.anim_duration_long));
   

  1. 實(shí)現(xiàn)

MianActivity.onCreat();

設(shè)置MainActivty的進(jìn)出動(dòng)畫(huà)代碼如下

  private void setupWindowAnimations() {
        Transition slideTracition = TransitionInflater.from(this).inflateTransition(R.transition.slide_from_left);
        getWindow().setEnterTransition(slideTracition);
        getWindow().setExitTransition(slideTracition);
        //getWindow().setReenterTransition(buildExitTransition());
    }
    
  1. 分析Fade的步驟是怎么發(fā)生的
    1. ActivatyA 啟動(dòng) ActivityB
    2. Transition Framework找到一個(gè)ExitTransition震贵,并將其應(yīng)用于所有可見(jiàn)視圖。
    3. 在返回之前過(guò)渡框架執(zhí)行進(jìn)入和退出分別反向動(dòng)畫(huà)(如果我們定義的輸出returnTransition和reenterTransition水评,這些都已經(jīng)轉(zhuǎn)而執(zhí)行)

ReturnTransition&ReenterTransition

返回和重新輸入轉(zhuǎn)換分別是Enter和Exit的反向動(dòng)畫(huà)猩系。

  • EnterTransition < - > ReturnTransition
  • ExitTransition < - > ReenterTransition

如果未定義返回或重新輸入,Android將按照你之前設(shè)定的默認(rèn)的版本中燥。但是如果你定義它們寇甸,你可以有不同的轉(zhuǎn)換進(jìn)入和退出活動(dòng)。(如下圖)

image
  • 當(dāng)你從ActivityB返回到ActivityA的時(shí)候疗涉。需要重新制定ActivityB的退出動(dòng)畫(huà)拿霉,可以通過(guò)如下方式
Visiable slide = new Slide();
slide.setDuraing(500);
getWindow.setReturnTransition(slide);
//別直接調(diào)用finish();
finshAfterTransition();

效果圖

Without Return Transition With Return Transition
image
image
image
image

2.Share elements between Activity(元素共享)

共享元素過(guò)度動(dòng)畫(huà)的背后是通過(guò)過(guò)度動(dòng)畫(huà)將兩個(gè)不同布局中的不同view關(guān)聯(lián)起來(lái)。Transition框架知道用適當(dāng)?shù)膭?dòng)畫(huà)向用戶展示從一個(gè)view向另外 一個(gè)view過(guò)度咱扣。請(qǐng)記渍捞浴:共享元素過(guò)度的過(guò)程中,view并沒(méi)有真正從一個(gè)布局跑到另外一個(gè)布局闹伪,整個(gè)過(guò)程基本都是在后一個(gè)布局中完成的沪铭。

image
image

a) 允許過(guò)度動(dòng)畫(huà)

需要在/res/style.xml添加

   <item name="android:windowContentTransitions">true</item>
   

b) 在對(duì)應(yīng)的xml文件指定TransitionName屬性

res/layout/activity

  • 指定ImageView和TextView

注意:這里必須為共享的倆個(gè)元素指定同一個(gè)TransitionName壮池,不然不會(huì)出現(xiàn)共享效果

 <ImageView
        android:id="@+id/square_blue"
        style="@style/MaterialAnimations.Icon.Big"
        android:src="@drawable/circle_24dp"
        android:transitionName="@string/square_blue_name" />
<TextView
       android:id="@+id/title"   
       style="@style/MaterialAnimations.TextAppearance.Title.Invers"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_vertical|start"
       android:text="@{sharedSample.name}"
       android:transitionName="@string/sample_blue_title" />

c) 啟動(dòng)Activity


Intent intent = new Intent(activity,target);
ActivityOptionCompat option = ActiviyoptionCampat.makeSceneTransitionAnimation(activity,  
new Pair<View, String>(viewHolder.binding.sampleIcon, activity.getString(R.string.square_blue_name)),
new Pair<View, String>(viewHolder.binding.sampleName, activity.getString(R.string.sample_blue_title)));

startActivity(intent,option.toBundle());

這段代碼將生成這個(gè)美麗的過(guò)渡動(dòng)畫(huà):

image

那么在Fragment之間怎么實(shí)現(xiàn)呢?

a) 允許過(guò)度動(dòng)畫(huà)

需要在/res/style.xml添加

   <item name="android:windowContentTransitions">true</item>
   

b) 在對(duì)應(yīng)的xml文件指定TransitionName屬性

之前的倆個(gè)步驟和Activity之間共享元素的沒(méi)有太大差別杀怠。

c) 通過(guò)Shared Element方式啟動(dòng)fragment

  private void addNextFragment(Sample sample, ImageView blue, boolean b) {
        SharedElementFragment2 elementFragment2 = SharedElementFragment2.newInstance(sample);
        Slide slide = new Slide();
        slide.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
        slide.setSlideEdge(Gravity.RIGHT);
        ChangeBounds changeBounds = new ChangeBounds();
        changeBounds.setDuration(getResources().getInteger(R.integer.anim_duration_medium));
        elementFragment2.setEnterTransition(slide);
        elementFragment2.setAllowEnterTransitionOverlap(b);
        elementFragment2.setAllowReturnTransitionOverlap(b);
        elementFragment2.setSharedElementEnterTransition(changeBounds);
        getFragmentManager().beginTransaction().replace(R.id.sample2_content, elementFragment2).addToBackStack(null).addSharedElement(blue, getString(R.string.square_blue_name)).commit();
    }

效果如下

image

3.動(dòng)畫(huà)視圖布局元素

上面?zhèn)z種方式都是運(yùn)用于過(guò)度動(dòng)畫(huà)椰憋,那Transition FrameWork也可以被用做于改變布局中的某個(gè)特定的View,比如修改View的位置或者大小赔退。我們需要確定想改變的結(jié)果即可橙依。

1.我們需要告訴framework我們需要改動(dòng)界面的Ui

TransitionManager.beginDelayedTransition(viewRoot);

  • 這里的viewRoot是需要改變view當(dāng)前所在的根布局

2.改變View的屬性

  • 改變大小
 ViewGroup.LayoutParams params = view.getLayoutParams();
 params.witdh = 200;
 view.setlayoutParams(params);

  • 改變位置
  ViewGroup.LayoutParams params = view.getLayoutParams();
 params.gravity = Gravity.Left;
 view.setlayoutParams(params);

Size Position
image
image

4.共享元素+循環(huán)動(dòng)畫(huà)

循環(huán)顯示只是一個(gè)動(dòng)畫(huà)顯示或隱藏一組UI元素。它可以自API21或以上使用硕旗。

image
image

上圖發(fā)生了幾個(gè)步驟彭沼?了解了之前的共享元素后我們知道智什。

  • 黃色的小球共享于MainActivity和RevealActivity樱衷。
  • 當(dāng)共享動(dòng)畫(huà)結(jié)束之后榆骚,在RevealActivity中發(fā)生了倆組動(dòng)畫(huà)效果
    • Toolbar上
    • 底部四個(gè)球執(zhí)行了特定的動(dòng)畫(huà)

那我們應(yīng)該如何監(jiān)聽(tīng)共享元素的動(dòng)畫(huà)結(jié)束的時(shí)刻。

  private void setupEnterAnimations() {
        Transition transtion = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
        getWindow().setSharedElementEnterTransition(transtion);
        transtion.addListener(new Transition.TransitionListener() {
         
            @Override
            public void onTransitionEnd(Transition transition) {
                transition.removeListener(this);
                hideTarget();
                animateRevealShow(toolbar);
                animateButtonIn();
            }

           
        });
    }

res/transition/changebounds_with_arcmotion.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
               android:duration="@integer/anim_duration_long"
               android:interpolator="@android:interpolator/decelerate_cubic"
    >
    <changeBounds>
        <arcMotion
            android:maximumAngle="90"
            android:minimumHorizontalAngle="90"
            android:minimumVerticalAngle="0"/>
    </changeBounds>
</transitionSet>

ToolBar Animation

private void animateRevealShow(View viewRoot) {

    int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
    int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
    int finalRadius = Math.max(viewRoot.getWidth(), viewRoot.getHeight());

    Animator anim = ViewAnimationUtils.createCircularReveal(viewRoot, cx, cy, 0, finalRadius);
    viewRoot.setVisibility(View.VISIBLE);
    anim.setDuration(1000);
    anim.setInterpolator(new AccelerateInterpolator());
    anim.start();
}

四個(gè)小球的浮現(xiàn)的動(dòng)畫(huà)

private void animateButtonIn() {
        for (int i = 0; i < bgViewGroup.getChildCount(); i++) {
            View child = bgViewGroup.getChildAt(i);
            child.animate()
                    .setStartDelay(100 + i * DELAY)
                    .setInterpolator(new AccelerateInterpolator())
                    .alpha(1)
                    .scaleX(1)
                    .scaleY(1);
        }
    }

另一種效果

紅色小球的效果

image

紅球運(yùn)動(dòng)軌跡 res/transition/changebounds_with_arcmotion.xml(這里不是共享動(dòng)畫(huà))

res/transition/changebounds_with_arcmotion.xml

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
               android:duration="@integer/anim_duration_long"
               android:interpolator="@android:interpolator/decelerate_cubic"
    >
    <changeBounds>
        <arcMotion
            android:maximumAngle="90"
            android:minimumHorizontalAngle="90"
            android:minimumVerticalAngle="0"/>
    </changeBounds>
</transitionSet>

點(diǎn)擊紅色小球時(shí) 執(zhí)行 revealRed()

  private void revealRed() {
        final ViewGroup.LayoutParams params = btnRed.getLayoutParams();
        Transition transition = TransitionInflater.from(this).inflateTransition(R.transition.changebounds_with_arcmotion);
        transition.addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {

            }

            @Override
            public void onTransitionEnd(Transition transition) {
                animateRevealColor(bgViewGroup, R.color.sample_red);
                body.setText(R.string.reveal_body3);
                body.setTextColor(ContextCompat.getColor(RevealActivity.this, R.color.theme_red_background));
                btnRed.setLayoutParams(params);
            }

            @Override
            public void onTransitionCancel(Transition transition) {

            }

            @Override
            public void onTransitionPause(Transition transition) {

            }

            @Override
            public void onTransitionResume(Transition transition) {

            }
        });
        TransitionManager.beginDelayedTransition(bgViewGroup, transition);
        final RelativeLayout.LayoutParams relativeRarams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        relativeRarams.addRule(RelativeLayout.CENTER_IN_PARENT);
        btnRed.setLayoutParams(relativeRarams);
    }
    
    
    
    private void animateRevealColor(ViewGroup viewRoot, @ColorRes int color) {
        int cx = (viewRoot.getLeft() + viewRoot.getRight()) / 2;
        int cy = (viewRoot.getTop() + viewRoot.getBottom()) / 2;
        animateRevealColorFromCoordinates(viewRoot, color, cx, cy);
    }
    
    
    
     private Animator animateRevealColorFromCoordinates(ViewGroup root, @ColorRes int color, int cx, int cy) {
        int finalRadius = Math.max(root.getWidth(), root.getHeight());
        final Animator animator = ViewAnimationUtils.createCircularReveal(root, cx, cy, 0, finalRadius);
        root.setBackgroundColor(ContextCompat.getColor(this, color));
        animator.setDuration(getResources().getInteger(R.integer.anim_duration_long));
        animator.setInterpolator(new AccelerateInterpolator());
        animator.start();
        return animator;
    }

更多信息

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辛藻,一起剝皮案震驚了整個(gè)濱河市碘橘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吱肌,老刑警劉巖痘拆,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異氮墨,居然都是意外死亡纺蛆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)规揪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)桥氏,“玉大人,你說(shuō)我怎么就攤上這事猛铅∽种В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵奸忽,是天一觀的道長(zhǎng)堕伪。 經(jīng)常有香客問(wèn)我,道長(zhǎng)栗菜,這世上最難降的妖魔是什么欠雌? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮疙筹,結(jié)果婚禮上富俄,老公的妹妹穿的比我還像新娘禁炒。我一直安慰自己,他們只是感情好蛙酪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布齐苛。 她就那樣靜靜地躺著,像睡著了一般桂塞。 火紅的嫁衣襯著肌膚如雪凹蜂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天阁危,我揣著相機(jī)與錄音玛痊,去河邊找鬼。 笑死狂打,一個(gè)胖子當(dāng)著我的面吹牛擂煞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趴乡,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼对省,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了晾捏?” 一聲冷哼從身側(cè)響起蒿涎,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惦辛,沒(méi)想到半個(gè)月后劳秋,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胖齐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年玻淑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呀伙。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡补履,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剿另,到底是詐尸還是另有隱情干像,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布驰弄,位于F島的核電站麻汰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏戚篙。R本人自食惡果不足惜五鲫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望岔擂。 院中可真熱鬧位喂,春花似錦浪耘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至规婆,卻和暖如春澜躺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抒蚜。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工掘鄙, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嗡髓。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓操漠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饿这。 傳聞我的和親對(duì)象是個(gè)殘疾皇子浊伙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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