Fragment三:对Fragment切换,跳转的封装

时间:2021-07-30 15:13:29

概述:

在使用了良久的Fragment后,为了能够更方便更快捷更好的屏蔽掉fragment原有问题,于是自定对Fragemnt进行了使用的封装。

目录:
* 用法

用法

导入代码

在底部有类的完整源码,可自行Copy复制到项目。

所需Copy代码

FragmentController的初始化

  1. 在主activity中或者BaseActivity中,以成员变量初始化创建对象
public FragmentController mFragmentManager = new FragmentController(this);
  1. 在主activity中或者BaseActivity中的dispatchKeyEvent函数中,实现方法mFragmentManager.onBackPressedListener()接口调用
/** * Explain : 设定生效后退的间隔时间 * * @author LiXaing create at 2017/8/21 18:30 */
    public static final int MIN_CLICK_DELAY_TIME = 500;

    /** * Explain : 上一次点击后退的时间节点 * * @author LiXaing create at 2017/8/17 0:12 */
    private static long lastKeyDownTime = 0;

@SuppressLint("RestrictedApi")
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {//点击的是返回键
            /** Explain : 当高频率点击返回的时候,由于过渡动画的原因会导致程序Crash,所以需要设定, * 在过渡动画展示的过程中,则不允许继续popFragment * @author LiXaing create at 2017/8/17 0:07*/
            long currentTime = Calendar.getInstance().getTimeInMillis();
            /** Explain : 动画时间为300,MIN_CLICK_DELAY_TIME为400,是为了动画完全结束后再允许下一次的pop * @author LiXaing create at 2017/8/17 0:09*/
            if (currentTime - lastKeyDownTime < MIN_CLICK_DELAY_TIME) {
                return true;
            }
            lastKeyDownTime = currentTime;

            if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {//按键的按下事件
                mFragmentManager.onBackPressedListener();
            } else if (event.getAction() == KeyEvent.ACTION_UP && event.getRepeatCount() == 0) {}
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
  1. 在所有fragment的基类BaseFragment中的onCreateView中初始化FragmentController对象
 mActivity = (MainActivity) getActivity();//此处的MainActivity是主activity其父类BaseActivity初始化创建了FragmentController实例对象,此处自行修改为初始化创建了FragmentController实例对象的activity即可 mFragmentManager = mActivity.mFragmentManager;
  1. 在所有fragment的基类BaseFragment中实现一个空函数
/** * Explain : 需要监听后退的Fragment子类就复写实现此方法 *@return : 当子类返回true,则认为当前后退由子类自己执行,不执行后退操作,全权交给子类自己去处理 * 当子类返回false,则认为当前子类不做处理,直接退出当前fragment * @author LiXaing create at 2017/7/19 17:54 */
    protected boolean onBackPressed() {return false;}

API示例

getInstanceAaddFragment()
                .setFrameID(R.id.realcontent)//传入展示xml布局中展示的FrameLayout的id,此处可在下面给的AddFragmentBean中设定默认值,那么在后面的常规使用中,就不许要再设定
                .setFragment(fragment)//设置需要跳转的Fragment
                .setBundle(bundle)//需要传递的Bundle
                .setAddToBackStack(true)//添加入回退栈,false则不加入,默认为false
                .setAliasName("Alias")//设置当前Fragment的别名,当没传入,默认为calssName
                .setOpenAnimation(true)//是否开启加载动画,默认为true
                .setShow(true)//commit后,是否就直接展示出来,false则不展示,默认为true
                .setChildFragment(true)//当前跳转的Fragment是否是被嵌套的,如果是则需要设定为true,默认为false
                .setLoadTtpe(AddFragmentBean.LoadTtpe.add)//跳转的加载类型,有两个枚举类型,AddFragmentBean.LoadTtpe.add、AddFragmentBean.LoadTtpe.replace
                .commit();//提交完成的设定

常规调用

//上面给的是全面的参数设定,在一般的常规使用跳转,就如下,非常简洁的一行代码。
getInstanceAaddFragment().setFragment(fragment).commit();
//另外如果有什么需求,可以按照参数设定的解释,自行给出设定就好了

所需Copy代码

FragmentManager


/** * Created by Administrator on 2018/1/30. */

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;

import com.icarzoo.project.boss.bean.basebean.AddFragmentBean;
import com.icarzoo.project.ui.MainActivity;
import com.icarzoo.project_base_config.utill.LogSwitchUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;

/** Explain : 用于管理Fragmen的: * 跳转 * 回退 * 回退监听 * 对Fragment的栈管理 * @author LiXiang create at 2018/1/30 18:46*/
public class FragmentController {

    private final FragmentManager supportFragmentManager;

    private FragmentActivity mActivity;
    private Fragment baseFragment;

    public FragmentController(FragmentActivity activity){
        this.mActivity = activity;
        this.supportFragmentManager = mActivity.getSupportFragmentManager();

    }

    public void setBaseFragment(Fragment baseFragment) {
        this.baseFragment = baseFragment;
    }

    /** Explain : Fragment的回退监听 * @author LiXiang create at 2018/1/30 19:03*/
    @SuppressLint("RestrictedApi")
    public void onBackPressedListener(){
        LogSwitchUtils.Log("回退","dispatchKeyEvent--Down");
        android.support.v4.app.FragmentManager fm = getFragmentManager(false);
        LogSwitchUtils.Log("回退",""+fm.getBackStackEntryCount()+" name:"+this.getClass().getSimpleName());

        if (fm.getBackStackEntryCount() > 1) {
            @SuppressLint("RestrictedApi")
            BaseFragment fragment = (BaseFragment) getFragments().get(fm.getBackStackEntryCount()-1);
            if (fragment != null) {
                LogSwitchUtils.Log("回退","当前Fragment的名字"+fragment.getClass().getSimpleName());
                /** Explain : 判断上一个fragment是否需要监听后退事件,当需要的时候则执行 * @author LiXiang create at 2017/12/8 14:44*/
                /** Explain : 当当前的fragment没有后退监听则看其内部有没有chlild,有看child有没有后退监听 * @author LiXiang create at 2017/12/8 15:57*/
                android.support.v4.app.FragmentManager fmChild = fragment.getChildFragmentManager();
                if (fmChild.getFragments()!= null && fmChild.getFragments().size() > 0) {
                    /** Explain : 先循环子类需要执行的回退事件 * @author LiXiang create at 2018/3/21 11:47*/
                    for (Fragment fragment1 : fmChild.getFragments()) {
                        BaseFragment BFFragment1 = (BaseFragment) fragment1;
                        if (BFFragment1 != null) {
                            LogSwitchUtils.Log("回退","子fragment的名字:"+BFFragment1.getClass().getSimpleName());
                            if (BFFragment1.isShow && BFFragment1.onBackPressed() == false) {
                                fm.popBackStack();
                            }
                        }
                    }

                    /** Explain : 执行父Fragment的回退事件 * @author LiXiang create at 2018/3/21 11:47*/
                    if (!fragment.onBackPressed()) {
                        fm.popBackStack();
                    }

                }else {
                    if (!fragment.onBackPressed()) {
                        fm.popBackStack();
                    }
                }
            }
        }else {
            BaseActivity activity = (BaseActivity) mActivity;
            activity.exitApp();
        }
    }



    /** * @apiNote Fragment的跳转封装 * @author LiXaing * create at 2017/4/30 19:38 */
    public AddFragmentBean getInstanceAaddFragment() {
        return new AddFragmentBean() {
            @Override
            public void AddFragmentListener() {
                Message message = new Message();
                message.obj = this;
                if (isOpenAnimation()) {
                    handler.sendMessageDelayed(message,305);
                }else {
                    handler.sendMessageDelayed(message,5);
                }
            }
        };
    }


    Handler handler = new Handler(new Handler.Callback(){
        @Override
        public boolean handleMessage(Message msg) {
            AddFragmentBean mAddFragmentBean = (AddFragmentBean) msg.obj;
                            addFragment(mAddFragmentBean);
// selectFragmentShow(msg.what);
            return true;
        }
    });



    public ArrayList<Fragment> getFragments() {
        ArrayList<Fragment> fragments1 = new ArrayList<>();
        @SuppressLint("RestrictedApi") List<Fragment> fragments = getFragmentManager(false).getFragments();
        for (Fragment fragment : fragments) {
            if (fragment != null) {
                fragments1.add(fragment);
            }
        }
        return fragments1;

    }

    @SuppressLint("RestrictedApi")
    public void addFragment(AddFragmentBean addFragmentBean) {
        addFragmentBean.fragment.setArguments(addFragmentBean.bundle);
        FragmentManager fm;
        /** Explain : 判断是否是Fragment中的Fragment * @author LiXiang create at 2017/10/12 18:18*/
        if (addFragmentBean.isChildFragment) {
            LogSwitchUtils.Log("addFragment ",getFragmentManager(false).getBackStackEntryCount()-1+"");
            LogSwitchUtils.Log("addFragment Fragments",getFragmentManager(false).getFragments()+"");


            LogSwitchUtils.Log("addFragment 2",getFragmentManager(false).getBackStackEntryCount()-1+"");
            LogSwitchUtils.Log("addFragment Fragments 2",getFragments().size()+"");

            fm =  getFragmentManager(true);
// fm = addFragmentBean.baseFragment.getChildFragmentManager();
            BaseFragment BFfragment = (BaseFragment) addFragmentBean.fragment;
            LogSwitchUtils.Log("isChildFragment",""+addFragmentBean.isChildFragment()+" name:"+BFfragment.getClass().getSimpleName());
        }  else {
            fm = supportFragmentManager;
        }
        if (fm == null) {
            return;
        }
        FragmentTransaction tx = fm.beginTransaction();
        if (addFragmentBean.loadTtpe == AddFragmentBean.LoadTtpe.add) {
            tx.add(addFragmentBean.FrameID, addFragmentBean.fragment, addFragmentBean.fragment.getClass().getName());
        } else {
            tx.replace(addFragmentBean.FrameID, addFragmentBean.fragment, addFragmentBean.fragment.getClass().getName());
        }
        if (addFragmentBean.addToBackStack && addFragmentBean.isChildFragment == false) {
// aliasName = fragment.getClass().getName();
            if (addFragmentBean.aliasName == null) {
                tx.addToBackStack(addFragmentBean.fragment.getClass().getName());
                LogSwitchUtils.Log("addFragmentBean.fragment.getClass:", addFragmentBean.fragment.getClass().getSimpleName());
                LogSwitchUtils.Log("addFragmentBean.fragment.getClass:", addFragmentBean.fragment.getClass().getName());
            } else {
                tx.addToBackStack(addFragmentBean.aliasName);
            }
        }
        if (!addFragmentBean.isShow()) {
            tx.hide(addFragmentBean.fragment);
            BaseFragment bf = (BaseFragment) addFragmentBean.fragment;
            bf.isShow = false;
        }
        tx.commitAllowingStateLoss();
    }




    /** * show一个Fragment,hide另一个/多个Fragment ; 主要用于类似微信主页那种 切换tab的情况 * * @param showFragment 需要show的Fragment * @param hideFragment 需要hide的Fragment * @param isChildFragment 当时Fragment是否是在Fragment中的fragment */
    public void showHideFragment(Fragment showFragment, Fragment hideFragment, Boolean isChildFragment) {

        if (showFragment == hideFragment) return;
        FragmentManager fm = getFragmentManager(isChildFragment);
        FragmentTransaction ft = fm.beginTransaction();
        if (hideFragment == null) {
            @SuppressLint("RestrictedApi") List<Fragment> fragmentList = fm.getFragments();
            if (fragmentList != null) {
                for (Fragment fragment : fragmentList) {
                    if (fragment != null && fragment != showFragment) {
                        ft.hide(fragment);
                        BaseFragment bf = (BaseFragment) fragment;
                        bf.isShow = false;
                        LogSwitchUtils.Log("fragmentName",fragment.getClass().getSimpleName());
                    }
                }
            }
        } else {
            ft.hide(hideFragment);
            BaseFragment bf = (BaseFragment) hideFragment;
            bf.isShow = false;
        }
        ft.show(showFragment);
        BaseFragment bf = (BaseFragment) showFragment;
        bf.isShow = true;
        ft.commitAllowingStateLoss();
    }


    /** * show一个Fragment,hide另一个/多个Fragment ; 主要用于类似微信主页那种 切换tab的情况 * * @param showFragment 需要show的Fragment的全路径名称 * @param hideFragment 需要hide的Fragment的全路径名称 * @param isChildFragment 当时Fragment是否是在Fragment中的fragment */
    protected void showHideFragment(String showFragment, String hideFragment, Boolean isChildFragment) {

        if (showFragment == hideFragment) return;

        FragmentManager fm = getFragmentManager(isChildFragment);
        FragmentTransaction ft = fm.beginTransaction();

        if (hideFragment == null) {
            @SuppressLint("RestrictedApi") List<Fragment> fragmentList = getFragments();
            if (fragmentList != null) {
                for (Fragment fragment : fragmentList) {
                    if (fragment != null && fragment.getClass().getName() != showFragment) {
                        ft.hide(fragment);
                        BaseFragment bf = (BaseFragment) fragment;
                        bf.isShow = false;
                    }
                }
            }
        } else {
            Fragment hideFragment1 = fm.findFragmentByTag(hideFragment);
            ft.hide(hideFragment1);
            BaseFragment bf = (BaseFragment) hideFragment1;
            bf.isShow = false;
        }
        if (fm.findFragmentByTag(showFragment) != null) {
            Fragment showFragment1 = fm.findFragmentByTag(showFragment);
            ft.show(showFragment1);
            BaseFragment bf = (BaseFragment) showFragment1;
            bf.isShow = true;
        }
        ft.commitAllowingStateLoss();
    }

    /** * Explain : 展示某一个Fragemnt * * @author LiXiang create at 2017/10/4 16:45 */
    public Fragment showFragment(Fragment showFragment, boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);
        BaseFragment bf = (BaseFragment) showFragment;
        bf.isShow = true;
        fm.beginTransaction().show(showFragment).commitAllowingStateLoss();
        return showFragment;
    }

    /** * Explain : 展示某一个Fragemnt * * @author LiXiang create at 2017/10/4 16:45 */
    protected void showFragment(String showFragmentTag, boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);
        Fragment showFragment1 = fm.findFragmentByTag(showFragmentTag);
        BaseFragment bf = (BaseFragment) showFragment1;
        bf.isShow = true;
        fm.beginTransaction().show(showFragment1).commitAllowingStateLoss();
    }


    /** * Explain : 隐藏某一个Fragemnt * * @author LiXiang create at 2017/10/4 16:45 */
    protected Fragment hideFragment(Fragment hideFragment, boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);
        BaseFragment bf = (BaseFragment) hideFragment;
        bf.isShow = false;
        fm.beginTransaction().hide(hideFragment).commitAllowingStateLoss();
        return hideFragment;
    }

    /** * Explain : 隐藏某一个Fragemnt * * @author LiXiang create at 2017/10/4 16:45 */
    protected void hideFragment(String hideFragmentTag, boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);
        Fragment hideFragment = fm.findFragmentByTag(hideFragmentTag);
        BaseFragment bf = (BaseFragment) hideFragment;
        bf.isShow = false;
        fm.beginTransaction().hide(hideFragment).commitAllowingStateLoss();
    }

    protected void removeFragment(Fragment removeFragment, boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);
        fm.beginTransaction().remove(removeFragment).commit();
    }

    protected void removeFragment(String Tag, boolean isChildFragment) {
        FragmentManager fm= getFragmentManager(isChildFragment);
        fm.beginTransaction().remove(fm.findFragmentByTag(Tag)).commitAllowingStateLoss();
    }

    protected void removeAllFragment(boolean isChildFragment) {
        FragmentManager fm = getFragmentManager(isChildFragment);


        @SuppressLint("RestrictedApi") List<Fragment> fragmentList = getFragments();
        if (fragmentList != null) {
            for (Fragment fragment : fragmentList) {
                if (fragment != null) {
                    fm.beginTransaction().remove(fragment);
                }
            }
        }

    }

    @SuppressLint("RestrictedApi")
    private FragmentManager getFragmentManager(boolean isChildFragment){
// System.out.println("getFragmentManager: "+supportFragmentManager.getBackStackEntryCount()+"");
// System.out.println("getFragmentManager name: "+supportFragmentManager.getFragments().get(supportFragmentManager.getBackStackEntryCount()-1).getClass().getName());
        FragmentManager fm;
        if (isChildFragment) {
// fm = supportFragmentManager.getFragments().get(supportFragmentManager.getBackStackEntryCount()-1).getChildFragmentManager();;
            fm = getFragments().get(supportFragmentManager.getBackStackEntryCount()-1).getChildFragmentManager();;

        } else {
            fm = supportFragmentManager;
        }
        return fm;
    }



    /** * Explain : 设定生效后退的间隔时间 * * @author LiXaing create at 2017/8/21 18:30 */
    public static final int MIN_CLICK_DELAY_TIME = 500;

    /** Explain : 设定生效动画的的间隔时间 * @author LiXaing create at 2017/8/21 18:31*/
// public static final int MIN_ANIMATION_TIME = 300;

    /** * Explain : 上一次点击后退的时间节点 * * @author LiXaing create at 2017/8/17 0:12 */
    private static long lastKeyDownTime = 0;

    /** Explain : 弹栈的方式 * @author LiXiang create at 2018/1/31 17:33*/
    public enum popType {
        INCLUDING_YOURSELF,//包括自己
        NOT_INCLUDING_YOURSELF;//不包括自己
    }

    /** * Explain : 选择弹出Fragment的方式 * * @param isHaveFlage 是否一次弹出多个Fragment * @param nameTag 一次弹出多个Fragment,回退到指定的nameTag的Fragment * @param type 一次弹出多个Fragment,的类型,是否包含自身一起弹出 * @author LiXaing create at 2017/8/21 18:24 */
    public void switchPopBackStack(BaseFragment baseFragment,boolean isHaveFlage, String nameTag, popType type) {
        /** Explain : 当高频率点击返回的时候,由于过渡动画的原因会导致程序Crash,所以需要设定, * 在过渡动画展示的过程中,则不允许继续popFragment * @author LiXaing create at 2017/8/17 0:07*/
        long currentTime = Calendar.getInstance().getTimeInMillis();
        /** Explain : 动画时间为300,MIN_CLICK_DELAY_TIME为400,是为了动画完全结束后再允许下一次的pop * @author LiXaing create at 2017/8/17 0:09*/
        if (currentTime - lastKeyDownTime < MIN_CLICK_DELAY_TIME) {
            return;
        }
        lastKeyDownTime = currentTime;
        if (!baseFragment.onBackPressed()) {
            LogSwitchUtils.Log("switchPopBackStack", "内部方法");
            if (!isHaveFlage) {
                baseFragment.getFragmentManager().popBackStack();
            } else {
                if (type.equals(popType.INCLUDING_YOURSELF)) {
                    LogSwitchUtils.Log("switchPopBackStack", "INCLUDING_YOURSELF");
                    baseFragment.getFragmentManager().popBackStack(nameTag, FragmentManager.POP_BACK_STACK_INCLUSIVE);
                } else {
                    baseFragment.getFragmentManager().popBackStack(nameTag, 0);
                }
            }
        }
    }



}

AddFragmentBean



import android.os.Bundle; import android.support.v4.app.Fragment; import com.icarzoo.R; /** * Created by lixiang on 2017/4/30. */ public abstract class AddFragmentBean { /**@author LiXiang create at 2018/1/31 17:19*/ /**Explain : FrameID : 当Fragment展示的界面的ID */ public int FrameID = R.id.realcontent; /**@author LiXiang create at 2018/1/31 17:19*/ /**Explain : fragment:当前需要展示的fragment */ public Fragment fragment; /**@author LiXiang create at 2018/1/31 17:19*/ /**Explain : bundle:fragment跳转中需要传递数据用的bundle */ public Bundle bundle = null; /**@author LiXiang create at 2018/1/31 17:18*/ /**Explain : aliasName : 设置当前Fragement的aliasName,当不设置默认为null的时候,会默认为当前类的全路径名称 */ public String aliasName = null; /**@author LiXiang create at 2018/1/31 17:18*/ /**Explain : addToBackStack : 是否添加到回退栈中,默认为true(添加) */ public boolean addToBackStack = true; /**@author LiXiang create at 2018/1/31 17:16*/ /**Explain : isChildFragment : 当前的fragment是否是属于在当前Fragemnt里展示,当是的时候需要设置为true,添加到childManager中 */ public boolean isChildFragment= false; /**@author LiXiang create at 2018/1/31 17:17*/ /**Explain : isShow : 加载完成之后是否展示,默认为展示 */ public boolean isShow= true; /**@author LiXiang create at 2018/1/31 17:18*/ /**Explain : LoadTtpe:在manager栈中的添加方式;有两种:add和replace;默认为add */ public LoadTtpe loadTtpe = LoadTtpe.add; public enum LoadTtpe{ add, replace; } public boolean isOpenAnimation= true; public boolean isOpenAnimation() { return isOpenAnimation; } public AddFragmentBean setOpenAnimation(boolean openAnimation) { isOpenAnimation = openAnimation; return this; } public boolean isShow() { return isShow; } public AddFragmentBean setShow(boolean show) { isShow = show; return this; } public boolean isChildFragment() { return isChildFragment; } public AddFragmentBean setChildFragment(boolean childFragment) { isChildFragment = childFragment; return this; } public LoadTtpe getLoadTtpe() { return loadTtpe; } public AddFragmentBean setLoadTtpe(LoadTtpe loadTtpe) { this.loadTtpe = loadTtpe; return this; } public boolean isAddToBackStack() { return addToBackStack; } public AddFragmentBean setAddToBackStack(boolean addToBackStack) { this.addToBackStack = addToBackStack; return this; } public int getFrameID() { return FrameID; } public AddFragmentBean setFrameID(int frameID) { FrameID = frameID; return this; } public Fragment getFragment() { return fragment; } public AddFragmentBean setFragment(Fragment fragment) { this.fragment = fragment; return this; } public Bundle getBundle() { return bundle; } public AddFragmentBean setBundle(Bundle bundle) { this.bundle = bundle; return this; } public String getAliasName() { return aliasName; } public AddFragmentBean setAliasName(String aliasName) { this.aliasName = aliasName; return this; } public void commit(){ AddFragmentListener(); } public abstract void AddFragmentListener(); }