簡單易用多功能Fragment架構(gòu)

前言

從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秒的動畫時間

Anim.gif
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());
Tab.gif

模塊化流程式(使用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);
    }
FlowMode.gif

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地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刀疙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扫倡,更是在濱河造成了極大的恐慌谦秧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撵溃,死亡現(xiàn)場離奇詭異油够,居然都是意外死亡,警方通過查閱死者的電腦和手機征懈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來揩悄,“玉大人卖哎,你說我怎么就攤上這事∩拘裕” “怎么了亏娜?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹬挺。 經(jīng)常有香客問我维贺,道長,這世上最難降的妖魔是什么巴帮? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任溯泣,我火速辦了婚禮,結(jié)果婚禮上榕茧,老公的妹妹穿的比我還像新娘垃沦。我一直安慰自己,他們只是感情好用押,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布肢簿。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪池充。 梳的紋絲不亂的頭發(fā)上桩引,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音收夸,去河邊找鬼坑匠。 笑死,一個胖子當著我的面吹牛咱圆,可吹牛的內(nèi)容都是我干的笛辟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼序苏,長吁一口氣:“原來是場噩夢啊……” “哼手幢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起忱详,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤围来,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后匈睁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體监透,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年航唆,在試婚紗的時候發(fā)現(xiàn)自己被綠了胀蛮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡糯钙,死狀恐怖粪狼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情任岸,我是刑警寧澤再榄,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站享潜,受9級特大地震影響困鸥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剑按,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一疾就、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艺蝴,春花似錦虐译、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侮攀。三九已至,卻和暖如春厢拭,著一層夾襖步出監(jiān)牢的瞬間兰英,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工供鸠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留畦贸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓楞捂,卻偏偏與公主長得像薄坏,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子寨闹,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容