Fragment的管理與內(nèi)核(二):Fragment轉(zhuǎn)場動畫

方法一:通過setCustomAnimations實現(xiàn)

在activity中開啟fragment時,F(xiàn)ragmentTransaction在add()或replace()之前,調(diào)用setCustomAnimations()來實現(xiàn)fragment轉(zhuǎn)場動畫;

getSupportFragmentManager()
                .beginTransaction()
                .setCustomAnimations(R.anim.slide_right_in,R.anim.slide_right_out,
                        R.anim.slide_right_in,R.anim.slide_right_out)
                .add(R.id.framlayout,new AIFilePickerFragment())
                .addToBackStack("")
                .commit();

setCustomAnimations()方法還有一個兩個參數(shù)的重載方法可以使用;
該方法需要在資源文件res/anim下添加轉(zhuǎn)場動畫,如下:

  • 進場動畫slide_right_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime">
    <translate
        android:toXDelta="0.0"
        android:fromXDelta="100.0%p" />
</set>

  • 出場動畫slide_right_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime">
    <translate
        android:toXDelta="100.0%p"
        android:fromXDelta="0.0" />

</set>

注意:1.該方法一定要在add或replace之前調(diào)用,否則無效;2.setCustomAnimations方法有一個很大的bug,就是在內(nèi)存重啟后所有設(shè)置的動畫都將失效。

image

方法二: setTranseion和onCreateAnimation配合實現(xiàn)

setTranseion是FragmentTransaction的方法,而onCreateAnimation是Fragment的方法,一般兩個方法需要配合使用。而且它們不會像setCustomAnimations一樣,即使是內(nèi)存重啟也不會失效,因為他們是動態(tài)調(diào)用的。
先來看一下setTranseion方法:

/**
     * Select a standard transition animation for this transaction.  May be
     * one of {@link #TRANSIT_NONE}, {@link #TRANSIT_FRAGMENT_OPEN},
     * or {@link #TRANSIT_FRAGMENT_CLOSE}
     */
    public abstract FragmentTransaction setTransition(@Transit int transit);

很明顯,要實現(xiàn)動畫,我們只能傳TRANSIT_FRAGMENT_OPEN和TRANSIT_FRAGMENT_CLOSE,他們分別表示進場和退場,首先使用FragmentTransaction設(shè)置Transeion:

 getSupportFragmentManager()
                .beginTransaction()
                .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .add(R.id.framlayout,new AIFilePickerFragment())
                .addToBackStack("")
                .commit();

單獨使用setTranseion的話,F(xiàn)ragmentManager會生成默認的動畫;源碼如下:

//根據(jù)transit或動作拿animAttr
    public static int transitToStyleIndex(int transit, boolean enter) {
        int animAttr = -1;
        switch (transit) {
            case FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
                animAttr = enter ? ANIM_STYLE_OPEN_ENTER : ANIM_STYLE_OPEN_EXIT;
                break;
            case FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
                animAttr = enter ? ANIM_STYLE_CLOSE_ENTER : ANIM_STYLE_CLOSE_EXIT;
                break;
            case FragmentTransaction.TRANSIT_FRAGMENT_FADE:
                animAttr = enter ? ANIM_STYLE_FADE_ENTER : ANIM_STYLE_FADE_EXIT;
                break;
        }
        return animAttr;
    }

    //根據(jù)animAttr生成動畫
    switch (styleIndex) {
            case ANIM_STYLE_OPEN_ENTER:
                return makeOpenCloseAnimation(mHost.getContext(), 1.125f, 1.0f, 0, 1);
            case ANIM_STYLE_OPEN_EXIT:
                return makeOpenCloseAnimation(mHost.getContext(), 1.0f, .975f, 1, 0);
            case ANIM_STYLE_CLOSE_ENTER:
                return makeOpenCloseAnimation(mHost.getContext(), .975f, 1.0f, 0, 1);
            case ANIM_STYLE_CLOSE_EXIT:
                return makeOpenCloseAnimation(mHost.getContext(), 1.0f, 1.075f, 1, 0);
            case ANIM_STYLE_FADE_ENTER:
                return makeFadeAnimation(mHost.getContext(), 0, 1);
            case ANIM_STYLE_FADE_EXIT:
                return makeFadeAnimation(mHost.getContext(), 1, 0);
        }

setTranseion和和Fragment的onCreateAnimation配合使用:

public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) {//表示是一個進入動作,比如add.show等
            if (enter) {//普通的進入的動作
                return AnimationUtils.loadAnimation(getContext(), R.anim.anim_bottom_in);
            } else {//比如一個已經(jīng)Fragmen被另一個replace,是一個進入動作,被replace的那個就是false
                return AnimationUtils.loadAnimation(getContext(), R.anim.anim_out);
            }
        } else if (transit == FragmentTransaction.TRANSIT_FRAGMENT_CLOSE) {//表示一個退出動作,比如出棧,hide,detach等
            if (enter) {//之前被replace的重新進入到界面或者Fragment回到棧頂
                return AnimationUtils.loadAnimation(getContext(), R.anim.anim_in);
            } else {//Fragment退出,出棧
                return AnimationUtils.loadAnimation(getContext(), R.anim.anim_bottom_out);
            }
        }
        return null;
    }

transit對應(yīng)FragmentTransaction設(shè)置的動作,onCreateAnimation在Fragment的每個操作動作中都會被回調(diào),最好是配合FragmentTransaction的setTranseion方法使用,才能更加靈活的實現(xiàn)各種動畫,不然onCreateAnimation方法的transit參數(shù)永遠是0,而nextAnim與setCustomAnimations有關(guān),而一般不推薦使用setCustomAnimations。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容