前言
从Android3.0引入Fragment之后,日常开发中,业务组的同学实现各种界面总会用到Fragment进行实现.
但是相应的使用Fragment对比单纯使用Activity的坑太多了,具体可以查看Fragment全解析系列
为什么开发此库
近一年主要在做React-Native,近期重构项目重写桥接了部分RN的组件,业务组的原生使用Fragment时比较混乱,因此将Fragment的使用操作进行封装.
特性
- 适用于单Activity+多Fragment或者多Activity+多Fragment
- 使用于模块化,便于业务组的开发维护
- 支持Tab类型界面一句话调用显示
- 支持模块化流程式界面控制
- 支持fragment配合ViewPager的懒加载
- 支持Fragment动画入栈出栈的控制显示
- 支持单独设置某一个Fragment的动画
- 支持Fragment单个实例或多个实例
- 支持回退栈BackStack管理
- 支持类似Activity的startActivityForResult的回执信息
- 支持参数传递并且回执
动画设置
方法 | 解释 | 默认值 |
---|---|---|
useAnim | 是否使用Fragment动画 | false |
enterAnim | 入栈动画 | R.animator.fragment_slide_left_enter |
exitAnim | ---- | R.animator.fragment_slide_left_exit |
popEnterAnim | ---- | R.animator.fragment_slide_right_enter |
popExitAnim | 出栈动画 | R.animator.fragment_slide_right_exit |
注意使用的时候使用属性动画,否则出栈动画会有显示异常。
对于入栈动画和出栈动画只需要重写返回enterAnim和popExitAnim即可。
下图的动画是设置了3秒的动画时间
public class FlowModeActivity extends QuickActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.flowmode_activity);
startFragment(StartFragment.class);
}
@Override
public boolean useAnim() {
return true;
}
@Override
public int enterAnim() {
return super.enterAnim();
}
@Override
public int exitAnim() {
return super.exitAnim();
}
@Override
public int popEnterAnim() {
return super.popEnterAnim();
}
@Override
public int popExitAnim() {
return super.popExitAnim();
}
@Override
public int fragmentId() {
return R.id.rootview;
}
}
Tab类型(使用showFragment(XXX))
Tab类型的UI界面很常见,一般我们使用Hide,Show的方式,对应Fragment首次添加是这样的
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.fragment_container,fragment, tag); //首次添加
transaction.addToBackStack(tag);
transaction.commit();
在切换过程中
transaction.hide(fragment); //隐藏
transaction.show(fragment);
transaction.commit();
简单封装
public void switchFragment(Fragment fragment, Fragment targetFragment) {
if (!to.isAdded()) { // 先判断是否被add过
transaction.hide(from).add(R.id.content_frame, to).commit(); // 隐藏当前的fragment,add下一个到Activity中
} else {
transaction.hide(from).show(to).commit(); // 隐藏当前的fragment,显示下一个
}
}
使用起来还是过于繁琐,需要多次创建FragmentTransaction事物,现在你只需要一句话即可.
Tab类型的只会存在一个fragment实例
实例判断即可
/**
* Show a fragment.
*
* @param targetFragment fragment to display.
* @param {@link QuickFragment}.
*/
public final void showFragment(T targetFragment) {
try {
QuickFragment showFragment = findFragmentByTag(targetFragment);
if (showFragment == null) {
showFragment = targetFragment;
if (showFragment == null) {
return;
}
}
switchFragment(showFragment);
} catch (Exception e) {
e.printStackTrace();
}
}
Tab类型使用方式:
showFragment(FragmentOne.class);
showFragment(new FragmentOne());
模块化流程式(使用startFragment(XXX))
模块化流程式的Fragment一般用于模块或者流程,比如登录-注册-忘记密码等等,可以将其理解为用户模块,对页面采用Fragment处理进行流程控制化.着重于需要对Fragment的栈进行管理控制,模块化后的Fragment就像Activity一样使用
模块流程式类型的允许存在一个fragment实例
/**
* Show a fragment.
*
* @param mCurrentFragment displaying fragment,default is mCurrentFragment
* @param targetFragment fragment to display.
* @param stickyStack sticky back stack.
* @param requestCode requestCode.
* @param {@link QuickFragment}.
*/
protected final void startFragment(T mCurrentFragment, T targetFragment,
boolean stickyStack, int requestCode) {
FragmentTransaction fragmentTransaction = getFragmentTransaction();
if (mCurrentFragment != null) {
FragmentStackEntity thisStackEntity = mFragmentEntityMap.get(mCurrentFragment);
if (thisStackEntity != null) {
if (thisStackEntity.isSticky) {
mCurrentFragment.onPause();
mCurrentFragment.onStop();
fragmentTransaction.hide(mCurrentFragment);
} else {
fragmentTransaction.remove(mCurrentFragment).commit();
fragmentTransaction.commitNow();
fragmentTransaction = getFragmentTransaction();
mFragmentEntityMap.remove(mCurrentFragment);
mFragmentStack.remove(mCurrentFragment);
}
}
}
String fragmentTag = targetFragment.getClass().getSimpleName() + atomicInteger.incrementAndGet();
fragmentTransaction.add(fragmentId(), targetFragment, fragmentTag);
fragmentTransaction.addToBackStack(fragmentTag);
fragmentTransaction.commit();
FragmentStackEntity fragmentStackEntity = new FragmentStackEntity();
fragmentStackEntity.isSticky = stickyStack;
fragmentStackEntity.requestCode = requestCode;
targetFragment.setStackEntity(fragmentStackEntity);
mFragmentEntityMap.put(targetFragment, fragmentStackEntity);
mFragmentStack.add(targetFragment);
}
Fragment之间Intent单独传参
- 传递
Bundle bundle = new Bundle();
bundle.putString("msg", "我爱你");
QuickFragment fragment = fragment(ArgumentFragment.class, bundle);
startFragment(fragment);
- 接受
Bundle bundle = getArguments();
message = bundle.getString("msg");
startFragmentForResult()回执信息
- 请求
startFragmentForResquest(CallBackFragment.class, 100);
- 返回信息
Bundle bundle = new Bundle();
bundle.putString("message", editText.getText().toString());
setResult(RESULT_OK, bundle);
finish();
- 获取回执信息
@Override
public void onFragmentResult(int requestCode, int resultCode, @Nullable Bundle result) {
switch (requestCode) {
case 100: {
if (resultCode == RESULT_OK) {
String message = result.getString("message");
if (TextUtils.isEmpty(message)) {
Toast.makeText(activity, "没有返回信息", 1).show();
} else {
Toast.makeText(activity, message, 1).show();
}
} else if (resultCode == RESULT_CANCELED) {
}
break;
}
case 101: {
if (resultCode == RESULT_OK) {
String message = result.getString("message");
if (TextUtils.isEmpty(message)) {
Toast.makeText(activity, "没有返回信息", 1).show();
} else {
Toast.makeText(activity, message, 1).show();
}
} else if (resultCode == RESULT_CANCELED) {
}
break;
}
}
}
传递参数并且回执信息
结合单独发送消息以及获取回执消息即可(参见DEMO)
BackStack回退栈
保存回退栈
所谓保存回退栈意思为A-->B-->C,那么按返回键回来的时候会依次回到C-->B-->A
startFragment(BackStackFragment1.class, true);
不保存回退栈
同样的A-->B-->C-->D,如果我们在启动的时候不保存B和C,那么按返回键回来会直接D-->A,中间的B,C将不会出现
startFragment(BackStackFragment1.class, false);
懒加载
@Override
protected void initLazy() {
//懒加载设置值或者网络请求等
// textView.setText(content);
}
@Override
protected void initNotLazy() {
}
如果是没有配合ViewPager使用,那么初始化请求设置等操作直接在initNotLazy执行,如果在initLazy执行界面将不会显示
若有疑问,请在Github提交issue或者查看DEMO
QuickFragmen地址