前言
從Android3.0引入Fragment之后赵颅,日常開發(fā)中隘弊,業(yè)務(wù)組的同學(xué)實現(xiàn)各種界面總會用到Fragment進行實現(xiàn).
但是相應(yīng)的使用Fragment對比單純使用Activity的坑太多了沪么,具體可以查看Fragment全解析系列
為什么開發(fā)此庫
近一年主要在做React-Native山憨,近期重構(gòu)項目重寫橋接了部分RN的組件劳翰,業(yè)務(wù)組的原生使用Fragment時比較混亂印颤,因此將Fragment的使用操作進行封裝.
特性
- 適用于單Activity+多Fragment或者多Activity+多Fragment
- 使用于模塊化请祖,便于業(yè)務(wù)組的開發(fā)維護
- 支持Tab類型界面一句話調(diào)用顯示
- 支持模塊化流程式界面控制
- 支持fragment配合ViewPager的懶加載
- 支持Fragment動畫入棧出棧的控制顯示
- 支持單獨設(shè)置某一個Fragment的動畫
- 支持Fragment單個實例或多個實例
- 支持回退棧BackStack管理
- 支持類似Activity的startActivityForResult的回執(zhí)信息
- 支持參數(shù)傳遞并且回執(zhí)
動畫設(shè)置
方法 | 解釋 | 默認值 |
---|---|---|
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即可。
下圖的動畫是設(shè)置了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的方式刷晋,對應(yīng)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,顯示下一個
}
}
使用起來還是過于繁瑣眼虱,需要多次創(chuàng)建FragmentTransaction事物喻奥,現(xiàn)在你只需要一句話即可.
Tab類型的只會存在一個fragment實例
實例判斷即可
/**
* Show a fragment.
*
* @param targetFragment fragment to display.
* @param <T> {@link QuickFragment}.
*/
public final <T extends QuickFragment> 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 <T> {@link QuickFragment}.
*/
protected final <T extends QuickFragment> 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()回執(zhí)信息
- 請求
startFragmentForResquest(CallBackFragment.class, 100);
- 返回信息
Bundle bundle = new Bundle();
bundle.putString("message", editText.getText().toString());
setResult(RESULT_OK, bundle);
finish();
- 獲取回執(zhí)信息
@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;
}
}
}
傳遞參數(shù)并且回執(zhí)信息
結(jié)合單獨發(fā)送消息以及獲取回執(zhí)消息即可(參見DEMO)
BackStack回退棧
保存回退棧
所謂保存回退棧意思為A-->B-->C捏悬,那么按返回鍵回來的時候會依次回到C-->B-->A
startFragment(BackStackFragment1.class, true);
不保存回退棧
同樣的A-->B-->C-->D撞蚕,如果我們在啟動的時候不保存B和C,那么按返回鍵回來會直接D-->A过牙,中間的B,C將不會出現(xiàn)
startFragment(BackStackFragment1.class, false);
懶加載
@Override
protected void initLazy() {
//懶加載設(shè)置值或者網(wǎng)絡(luò)請求等
// textView.setText(content);
}
@Override
protected void initNotLazy() {
}
如果是沒有配合ViewPager使用甥厦,那么初始化請求設(shè)置等操作直接在initNotLazy執(zhí)行,如果在initLazy執(zhí)行界面將不會顯示
若有疑問寇钉,請在Github提交issue或者查看DEMO
QuickFragmen地址