美文网首页安卓常用技巧
Fragment进入退出动画(Fragment转场动画)

Fragment进入退出动画(Fragment转场动画)

作者: 码鲜生 | 来源:发表于2019-05-14 17:13 被阅读0次

    方法一:通过setCustomAnimations实现

    在activity中开启fragment时,FragmentTransaction在add()或replace()之前,调用setCustomAnimations()来实现fragment转场动画;

    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()方法还有一个两个参数的重载方法可以使用;
    该方法需要在资源文件res/anim下添加转场动画,如下:

    • 进场动画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之前调用,否则无效;2.setCustomAnimations方法有一个很大的bug,就是在内存重启后所有设置的动画都将失效。

    fragment转场动画.gif

    方法二: setTranseion和onCreateAnimation配合实现

    setTranseion是FragmentTransaction的方法,而onCreateAnimation是Fragment的方法,一般两个方法需要配合使用。而且它们不会像setCustomAnimations一样,即使是内存重启也不会失效,因为他们是动态调用的。
    先来看一下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);
    

    很明显,要实现动画,我们只能传TRANSIT_FRAGMENT_OPEN和TRANSIT_FRAGMENT_CLOSE,他们分别表示进场和退场,首先使用FragmentTransaction设置Transeion:

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

    单独使用setTranseion的话,FragmentManager会生成默认的动画;源码如下:

    //根据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;
        }
    
    
        //根据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 {//比如一个已经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对应FragmentTransaction设置的动作,onCreateAnimation在Fragment的每个操作动作中都会被回调,最好是配合FragmentTransaction的setTranseion方法使用,才能更加灵活的实现各种动画,不然onCreateAnimation方法的transit参数永远是0,而nextAnim与setCustomAnimations有关,而一般不推荐使用setCustomAnimations。

    参考:Fragment的转场动画

    相关文章

      网友评论

        本文标题:Fragment进入退出动画(Fragment转场动画)

        本文链接:https://www.haomeiwen.com/subject/aduooqtx.html