概述:
在使用了良久的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(); }