让android应用实现只有一个activity的fragmentOnlySupportActivity

自从fragment出现以来,很多app都开始使用fragment做界面,由于fragment的生命周期比activity丰富,如果管理不好fragment,就是增加开发难度,如果对fragment的生命周期管理到位就会事半功倍,按我的理解,fragment的生命周期其实就是activity生命周期的加强版,很多生命周期的方法和activity生命周期的方法是一个效果的,如果你的应用design不是android的那种design,很多都是自定义的,那么你可以尝试使用只有一个activity的编码(其实一般来说,在普通的开发中并没有什么卵用,但如果你使用插件技术吧fragment做出插件,界面跳转无需什么,可以增加删除,那意义就重大了)。

如何管理fragment的回退栈

一般的,你会想到使用popbackstack,其实popbackstack只是fragment的事务回退操作,注意了是事务,fragment的事务回退包括了fragment状态的回退,事务处理在处理自定义的复杂fragment跳转就会变得很繁琐,甚至不明白会应为不明白他的原理而研究他的源码!

在这里,我用的方法是hide,show,remove等方法对fragment经常自定义的管理。

假设你要启动一个fragment,那么将它实例化后add进来,add之前要对所有的fragment都做hide处理,不然底部会出现上一个fragment的背景,甚至能够点击。

假如你按了返回键,回到上一个fragment,那么从fragmentManger里面获取fragmentList(请勿对它操作,不然会出问题),注意了,这个fragmentList的顺序不一定跟你add的顺序一致,而且部分fragment销毁掉的,在这个list里面会空,对于没有顺序的fragmentList,我们需要对fragment设置Tag标记fragment是第几个add进去的,按返回键的时候,枚举一次fragmentList,按照tag,取到上一个界面的fragment,然后remove当前fragment,show出上一个fragment。

如何像activity那样finish掉指定界面?

如果你拿到他的实例,直接remove掉,如果你只有fragment的Class,那么枚举fragmentList,判断className相同后删除。

如果给fragment添加载入退出动画

抛开fragment动画,你一定会知道app中不一定全部activity载入动画是相同的,那么这个一个让fragmentOnlySupport一定也要能知道不同fragment对应不同的动画,此时,如何给fragment设置对应的动画?还是给fragment设置Tag,上面讲到fragment设置加载的index,那么index和动画一起加起来,可以用json作为字符串,把index和对应的动画都绑定在一起。

博客出处

创建实体与之对应:

public class FragmentTagVo {
    public FragmentTagVo(){};
    public FragmentTagVo(int index, String animType) {
        this.index = index;
        this.animType = animType;
    }
    public String animType;
    public int index;


    public static FragmentTagVo build(String json) {
        FragmentTagVo tagVo = new FragmentTagVo();
        try {
            JSONObject jsonObject = new JSONObject(json);
            tagVo.index = jsonObject.getInt("index");
            tagVo.animType = jsonObject.getString("animType");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tagVo;
    }

    @Override
    public String toString() {
        JSONObject jsonObject = new JSONObject();
        try {
            jsonObject.put("index",index);
            jsonObject.put("animType",animType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return jsonObject.toString();
    }
}

在加载fragment的时候设置tag:

            fragmentIndex++;
                FragmentTagVo tagVo = new FragmentTagVo(fragmentIndex,animType==null?AnimType.NONE.toString():animType.toString());
                try {
                    mFragmentTransaction.add(containerId, tagfragment, tagVo.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mFragmentTransaction.show(tagfragment);
                mFragmentTransaction.commitAllowingStateLoss();
                KeyboradUtil.hideSoftKeyboard(this);

返回时找到上一个fragment的方法:

                PLog.i("list:" + fragmentlist);
                for (int i = fragmentlist.size()-1; i >= 0 ; i--) {
                    Fragment fragment = fragmentlist.get(i);
                    if (!(fragment == null || !fragment.isVisible())) {//可视且不是没有设置view的fragment
                        //这里可以写应用自己的返回逻辑

                        //

                        Fragment backFragment = null;
                        PLog.d("tag:" + fragment.getTag());
                        FragmentTagVo tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class);
                        int fragIndex = tagVo.index-1;
                        Looper:
                        while (fragIndex >= 0) {//从list后面开始找,高效查找方法
                        FindByTag:
                            for (AnimType animType:AnimType.values()) {
                                tagVo = new FragmentTagVo(fragIndex,animType.toString());
                                backFragment = fragmentManager.findFragmentByTag(JSONObject.toJSONString(tagVo));
                                if (backFragment!=null) {
                                    break FindByTag;
                                }
                            }
                            PLog.d("backFragment:" + backFragment);
                            if (backFragment != null) {
                                PLog.d("backFragment add?:" + backFragment.isAdded());
                                PLog.d("backFragment removing?:" + backFragment.isRemoving());
                            }
                            if (backFragment == null || !backFragment.isAdded() || backFragment.isRemoving()) {
                                --fragIndex;
                            } else {
                                break Looper;
                            }
                        }
                        PLog.d("currFragment:" + fragment.getClass().getSimpleName());
                        PLog.d("backFragment:" + backFragment);

                    }
                }

处理完动画绑定在fragment的逻辑,开始往fragment添加动画。

先声明一个动画枚举类,包括以下动画:

public enum AnimType {
    NONE,//没有动画
    LeftInRightOut,//左进右出
    BottomInTopOut,//上进,往下出
    ZoomShow//fragment默认缩放
    ;
    public static int[] getAnimRes (AnimType animType){
        switch (animType) {
            case LeftInRightOut:
                return new int[]{R.anim.push_left_in,R.anim.push_left_out,R.anim.back_left_in, R.anim.back_right_out};
            case BottomInTopOut:
                return new int[]{R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out};
            default:
                return new int[]{0,0,0,0};
        }
    }
}

add之前添加动画:

public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction,@NonNull AnimType animType) {
                if (mFragmentTransaction == null) {
                    mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                }

                //動畫
                if (animType==AnimType.ZoomShow) {
                    mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                } else if (animType== AnimType.LeftInRightOut) {
                    mFragmentTransaction.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out,R.anim.back_left_in,R.anim.back_right_out);
                } else if (animType== AnimType.BottomInTopOut) {
                    mFragmentTransaction.setCustomAnimations(R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out);
                } else {
                    //NONE
                }     
}

退出时设置对于退出动画:

public void backPressed () {
......code for find back Fragment

if (backFragment != null) {
                            tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class);
                            AnimType exitAnim = null;
                            if(tagVo!=null)
                                for (AnimType animType:AnimType.values()) {
                                    if (animType.toString().equals(tagVo.animType.toString())) {
                                        exitAnim = animType;
                                    }
                                }

                            final Fragment animShowFragment = backFragment;
                            final Fragment animHideFragment = fragment;
                            if (exitAnim==null || exitAnim==AnimType.NONE) {
                                FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                mFragmentTransaction.show(animShowFragment);
                                mFragmentTransaction.remove(animHideFragment);
                                mFragmentTransaction.commitAllowingStateLoss();
                            } else if (exitAnim==AnimType.ZoomShow) {
                                FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
                                mFragmentTransaction.show(animShowFragment);
                                mFragmentTransaction.remove(animHideFragment);
                                mFragmentTransaction.commitAllowingStateLoss();
                            } else {
                                int[] animRes = AnimType.getAnimRes(exitAnim);
                                Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), animRes[3]);
                                animation.setAnimationListener(new Animation.AnimationListener() {
                                    @Override
                                    public void onAnimationStart(Animation animation) {

                                    }

                                    @Override
                                    public void onAnimationEnd(Animation animation) {
                                        FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                        mFragmentTransaction.show(animShowFragment);
                                        mFragmentTransaction.remove(animHideFragment);
                                        mFragmentTransaction.commitAllowingStateLoss();
                                        fragmentChangeing = false;
                                    }

                                    @Override
                                    public void onAnimationRepeat(Animation animation) {

                                    }
                                });
                                fragment.getView().startAnimation(animation);
                                backFragment.getView().setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), animRes[2]));
                            }
                        } else {
                            finish();
                        }
                    }//end if (!(fragment == null || !fragment.isVisible())) {//可视的

    .......code for do other
}

如果让fragment拦截返回事件,或实现带条件的返回?

重写activity的onBackPressed返回方法,加入以下代码,让fragment调用就Ok了:

 public void setCanBackPress(boolean can) {
        this.mCanBackPress = can;
    }

    protected boolean mCanBackPress = true;
    protected OnBackPressedListener onBackPressedListener;

    public void setOnBackPressedListener(OnBackPressedListener listener) {
        this.onBackPressedListener = listener;
    }

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null) {
            onBackPressedListener.OnBackKeyDown();
            return;
        }

        if (!mCanBackPress) {
            return;
        }
        backPressed();//该方法用于返回上一个fragment,如果没上一个界面了,最终执行finish
    }

如果打通这些fragments通信通道?实现像activity的onActivityResult方法一样

类似于广播者模式,每个fragment都可以是观察者和被观察者,用onActivityResult充当Observer接口,用枚举fragmentList的Fragment调用onActivityResult方法充当被观察者。有以下代码:

博客出处

public void pushMsgToSubFragments (boolean needShow,int pushCode,Intent pushData) {
        pushMsgToSubFragments(getSupportFragmentManager(), needShow,pushCode, Activity.RESULT_OK, pushData);
    }


    public void pushMsgToSubFragments (@NonNull FragmentManager fragmentManager,boolean needShow,int requestCode,int resultCode, Intent data) {
        List<Fragment> fragmentlist =  fragmentManager.getFragments();
        if (fragmentlist!=null)
            for (Fragment fragment:fragmentlist) {
                if (fragment==null) {
                    continue;
                }
                if (fragment.isAdded()) {
                    if (needShow) {
                        if (!fragment.isHidden()) {
                            PLog.i("send to:" + fragment);
                            fragment.onActivityResult(requestCode, resultCode, data);
                        }
                    } else {
                        PLog.i("send to:" + fragment);
                        fragment.onActivityResult(requestCode, resultCode, data);
                    }

                    //如果fragment里面还嵌套了fragment,继续观察
                    pushMsgToSubFragments(fragment.getChildFragmentManager(),needShow,requestCode,resultCode,data);
                }
            }
    }


    //Fragment里面重写onActivityResult接送观察类型和数据

如果activity调用其他activity,返回数据,继续重新onactivityresult方法:

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        PLog.i("onActivityResult:" + requestCode);
        try {
            super.onActivityResult(requestCode, resultCode, data);
        } catch (Exception e) {
            e.printStackTrace();
        }

        pushMsgToSubFragments(getSupportFragmentManager(), false, requestCode, resultCode, data);
    }

最后献上完整代码:


import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;


import java.util.ArrayList;
import java.util.List;

/**
 * Created by george.yang on 15/11/18.
 */
public abstract class FragmentOnlySupportActivity extends PlugBaseActivity {
    public abstract int getContainerId();
    private int containerId = getContainerId();

    public static boolean fragmentChangeing = false;

    public <T extends Fragment> T getFragment(@Nullable FragmentManager manager, Class clazz) {
        return getFragment(manager, false, clazz);
    }

    public <T extends Fragment> T getFragment(@Nullable FragmentManager manager, boolean showing, Class clazz) {
        if (clazz == null) {
            return null;
        }
        if (manager == null) {
            manager = getSupportFragmentManager();
        }
        List<Fragment> fragmentlist = manager.getFragments();
        if (fragmentlist != null) {
            for (Fragment fragment : fragmentlist) {
                if (fragment == null || fragment.isRemoving() || !fragment.isAdded() || (showing && fragment.isHidden())) {
                    continue;
                }
                if (clazz.getName().equals(fragment.getClass().getName())) {
                    return (T) fragment;
                } else {
                    Fragment fragmentInner = getFragment(fragment.getChildFragmentManager(), showing, clazz);
                    if (fragmentInner != null) {
                        return (T) fragmentInner;
                    }
                }
            }
        }
        return null;
    }

    public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction) {
        loadFragment(tagfragment,mFragmentTransaction, AnimType.LeftInRightOut);
    }

    public void loadFragment(Fragment tagfragment) {
        loadFragment(tagfragment,AnimType.LeftInRightOut);
    }

    public void loadFragment(String fragmenName) {
        try {
            loadFragment((Class<? extends Fragment>) Class.forName(fragmenName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void loadFragment(Class<? extends Fragment> fragmentClass) {
        try {
            loadFragment((Fragment) fragmentClass.newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public void loadFragment(Fragment tagfragment,@NonNull AnimType animType) {
        loadFragment(tagfragment, null, animType);
    }

    private int fragmentIndex;
    public void loadFragment(Fragment tagfragment, FragmentTransaction mFragmentTransaction,@NonNull AnimType animType) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            if (isDestroyed()) {
                return;
            }
        }
        if (isFinishing()) {
            return;
        }
        PLog.i("load:" + tagfragment);
        if (!fragmentChangeing) {
            fragmentChangeing = true;
            if (tagfragment!=null) {
                if (mFragmentTransaction == null) {
                    mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                }

                //動畫
                if (animType==AnimType.ZoomShow) {
                    mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                } else if (animType== AnimType.LeftInRightOut) {
                    mFragmentTransaction.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out,R.anim.back_left_in,R.anim.back_right_out);
                } else if (animType== AnimType.BottomInTopOut) {
                    mFragmentTransaction.setCustomAnimations(R.anim.push_bottom_in,R.anim.push_top_out,R.anim.push_bottom_in,R.anim.push_top_out);
                } else {
                    //NONE
                }

                List<Fragment> fragmentlist = getSupportFragmentManager().getFragments();
                if (fragmentlist != null)
                    for (int i = 0; i < fragmentlist.size(); i++) {
                        Fragment fragment = fragmentlist.get(i);
                        if (fragment != null) {
                            mFragmentTransaction.hide(fragment);
                        }
                    }

                fragmentIndex++;
                FragmentTagVo tagVo = new FragmentTagVo(fragmentIndex,animType==null?AnimType.NONE.toString():animType.toString());
                try {
                    mFragmentTransaction.add(containerId, tagfragment, JSONObject.toJSONString(tagVo));
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mFragmentTransaction.show(tagfragment);
                mFragmentTransaction.commitAllowingStateLoss();
                KeyboradUtil.hideSoftKeyboard(this);
            }
            fragmentChangeing = false;
        }
    }

    public void pushMsgToSubFragments (boolean needShow,int pushCode,Intent pushData) {
        pushMsgToSubFragments(getSupportFragmentManager(), needShow,pushCode, Activity.RESULT_OK, pushData);
    }


    public void pushMsgToSubFragments (@NonNull FragmentManager fragmentManager,boolean needShow,int requestCode,int resultCode, Intent data) {
        List<Fragment> fragmentlist =  fragmentManager.getFragments();
        if (fragmentlist!=null)
            for (Fragment fragment:fragmentlist) {
                if (fragment==null) {
                    continue;
                }
                if (fragment.isAdded()) {
                    if (needShow) {
                        if (!fragment.isHidden()) {
                            PLog.i("send to:" + fragment);
                            fragment.onActivityResult(requestCode, resultCode, data);
                        }
                    } else {
                        PLog.i("send to:" + fragment);
                        fragment.onActivityResult(requestCode, resultCode, data);
                    }

                    pushMsgToSubFragments(fragment.getChildFragmentManager(),needShow,requestCode,resultCode,data);
                }
            }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        PLog.i("onActivityResult0:" + requestCode);
        try {
            super.onActivityResult(requestCode, resultCode, data);
        } catch (Exception e) {
            e.printStackTrace();
        }

        pushMsgToSubFragments(getSupportFragmentManager(), false, requestCode, resultCode, data);
    }


    final List<Fragment> removeFragment = new ArrayList<>();
    public boolean removeFragment(Class clazz) {
        if (clazz == null) {
            return false;
        }
        synchronized (removeFragment) {
            List<Fragment> fragmentlist = getSupportFragmentManager().getFragments();
            if (fragmentlist != null) {
                for (Fragment fragment : fragmentlist) {
                    if (fragment == null) {
                        continue;
                    }
                    if (clazz.getName().equals(fragment.getClass().getName())) {
                        PLog.i("remove:" + clazz.getName());
                        removeFragment.add(fragment);
                    }
                }

                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                for (Fragment fragment : removeFragment) {
                    ft.remove(fragment);
                }
                ft.commitAllowingStateLoss();
                removeFragment.clear();
            }
            //                }
        }
        return true;
    }

    public void setCanBackPress(boolean can) {
        this.mCanBackPress = can;
    }

    protected boolean mCanBackPress = true;
    protected OnBackPressedListener onBackPressedListener;

    public void setOnBackPressedListener(OnBackPressedListener listener) {
        this.onBackPressedListener = listener;
    }

    @Override
    public void onBackPressed() {
        if (onBackPressedListener != null) {
            onBackPressedListener.OnBackKeyDown();
            return;
        }

        if (!mCanBackPress) {
            return;
        }
        backPressed();
    }

    //[博客出处](http://georgeyang.cn)
    public void backPressed () {
        boolean waitAnimEndUnLock = false;
        if (!fragmentChangeing) {
            fragmentChangeing = true;
            try {
                FragmentManager fragmentManager = getSupportFragmentManager();
                fragmentManager.executePendingTransactions();//同步结束
                List<Fragment> fragmentlist = fragmentManager.getFragments();
                if (fragmentlist==null) {
                    finish();
                }
                PLog.i("list:" + fragmentlist);
                for (int i = fragmentlist.size()-1; i >= 0 ; i--) {
                    Fragment fragment = fragmentlist.get(i);
                    if (!(fragment == null || !fragment.isVisible())) {//可视且不是没有设置view的fragment
                        //这里可以写应用自己的返回逻辑

                        //

                        Fragment backFragment = null;
                        PLog.d("tag:" + fragment.getTag());
                        FragmentTagVo tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class);
                        int fragIndex = tagVo.index-1;
                        Looper:
                        while (fragIndex >= 0) {
                        FindByTag:
                            for (AnimType animType:AnimType.values()) {
                                tagVo = new FragmentTagVo(fragIndex,animType.toString());
                                backFragment = fragmentManager.findFragmentByTag(JSONObject.toJSONString(tagVo));
                                if (backFragment!=null) {
                                    break FindByTag;
                                }
                            }
                            PLog.d("backFragment:" + backFragment);
                            if (backFragment != null) {
                                PLog.d("backFragment add?:" + backFragment.isAdded());
                                PLog.d("backFragment removing?:" + backFragment.isRemoving());
                            }
                            if (backFragment == null || !backFragment.isAdded() || backFragment.isRemoving()) {
                                --fragIndex;
                            } else {
                                break Looper;
                            }
                        }
                        PLog.d("currFragment:" + fragment.getClass().getSimpleName());
                        PLog.d("backFragment:" + backFragment);


                        if (backFragment != null) {
                            tagVo = JSONObject.parseObject(fragment.getTag(),FragmentTagVo.class);
                            AnimType exitAnim = null;
                            if(tagVo!=null)
                                for (AnimType animType:AnimType.values()) {
                                    if (animType.toString().equals(tagVo.animType.toString())) {
                                        exitAnim = animType;
                                    }
                                }

                            final Fragment animShowFragment = backFragment;
                            final Fragment animHideFragment = fragment;
                            if (exitAnim==null || exitAnim==AnimType.NONE) {
                                FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                mFragmentTransaction.show(animShowFragment);
                                mFragmentTransaction.remove(animHideFragment);
                                mFragmentTransaction.commitAllowingStateLoss();
                            } else if (exitAnim==AnimType.ZoomShow) {
                                FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                mFragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE);
                                mFragmentTransaction.show(animShowFragment);
                                mFragmentTransaction.remove(animHideFragment);
                                mFragmentTransaction.commitAllowingStateLoss();
                            } else {
                                int[] animRes = AnimType.getAnimRes(exitAnim);
                                Animation animation = AnimationUtils.loadAnimation(getApplicationContext(), animRes[3]);
                                animation.setAnimationListener(new Animation.AnimationListener() {
                                    @Override
                                    public void onAnimationStart(Animation animation) {

                                    }

                                    @Override
                                    public void onAnimationEnd(Animation animation) {
                                        FragmentTransaction mFragmentTransaction = getSupportFragmentManager().beginTransaction();
                                        mFragmentTransaction.show(animShowFragment);
                                        mFragmentTransaction.remove(animHideFragment);
                                        mFragmentTransaction.commitAllowingStateLoss();
                                        fragmentChangeing = false;
                                    }

                                    @Override
                                    public void onAnimationRepeat(Animation animation) {

                                    }
                                });
                                fragment.getView().startAnimation(animation);
                                backFragment.getView().setAnimation(AnimationUtils.loadAnimation(getApplicationContext(), animRes[2]));
                            }
                        } else {
                            finish();
                        }
                    }//end if (!(fragment == null || !fragment.isVisible())) {//可视的
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            KeyboradUtil.hideSoftKeyboard(this);
            if (!waitAnimEndUnLock) {
                PLog.i("unlock:338");
                fragmentChangeing = false;
            }
        }
    }



}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值