概述:
在使用了良久的Fragment后,为了能够更方便更快捷更好的屏蔽掉fragment原有问题,于是自定对Fragemnt进行了使用的封装。
目录:
* 用法
用法
导入代码
在底部有类的完整源码,可自行Copy复制到项目。
所需Copy代码
FragmentController的初始化
- 在主activity中或者BaseActivity中,以成员变量初始化创建对象
public FragmentController mFragmentManager = new FragmentController(this);
- 在主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);
}
- 在所有fragment的基类BaseFragment中的onCreateView中初始化FragmentController对象
mActivity = (MainActivity) getActivity();//此处的MainActivity是主activity其父类BaseActivity初始化创建了FragmentController实例对象,此处自行修改为初始化创建了FragmentController实例对象的activity即可
mFragmentManager = mActivity.mFragmentManager;
- 在所有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();
}