Fragment系列文章:
1、Fragment全解析系列(一):那些年踩過的坑
2、Fragment全解析系列(二):正確的使用姿勢
3、Fragment之我的解決方案:Fragmentation
如果你通讀了本系列的前兩篇,我相信你可以寫出大部分場景都能正常運行的Fragment了。如果你想了解更多,那么你可以看看我封裝的這個庫:Fragmentation。
本篇主要介紹這個庫,解決了一些BUG,使用簡單,提供實時查看棧視圖等實用功能。
源碼地址:Github,歡迎Fork,提Issues 。
Demo網盤下載
Demo演示:單Activity+多Fragment

Fragmentation
為"單Activity + 多Fragment的架構","多模塊Activity + 多Fragment的架構"而生,幫你簡化使用過程,修復了官方Fragment庫存在的一些BUG。
特性
1、為重度使用Fragment而生
2、提供了方便的管理Fragment的方法
3、有效解決Fragment重疊問題
4、實時查看Fragment的(包括嵌套Fragment)棧視圖,方便Fragment嵌套時的調試
5、增加啟動模式、startForResult等類似Activity方法
6、修復官方庫里pop(tag/id)出棧多個Fragment時的一些BUG
7、完美解決進出棧動畫的一些BUG,更自由的管理Fragment的動畫
如何使用
1、項目下app的build.gradle中依賴:
compile 'me.yokeyword:fragmentation:0.3.0' // appcompat v7包也是必須的
2、Activity繼承SupportActivity:
public class MainActivity extends SupportActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(...); if (savedInstanceState == null) { start(HomeFragment.newInstance()); } } /** * 設置Container的id,必須實現 */ @Override public int setContainerId() { return R.id.fl_container; } /** * 設置全局動畫,在SupportFragment可以自由更改其動畫 */ @Override protected FragmentAnimator onCreateFragmentAnimator() { // 默認豎向(和安卓5.0以上的動畫相同) return super.onCreateFragmentAnimator(); // 設置橫向(和安卓4.x動畫相同) // return new DefaultHorizontalAnimator(); // 設置自定義動畫 // return new FragmentAnimator(enter,exit,popEnter,popExit); }
3、Fragment繼承SupportFragment
API
SupportActivity
打開 棧視圖 的提示框,在復雜嵌套的時候,可以通過這個來清洗的理清不同階級的棧視圖。
// 彈出 棧視圖 提示框 showFragmentStackHierarchyView();
除此之外包含大部分SupportFragment的方法,請自行查看。
SupportFragment
1、啟動相關:
// 啟動新的Fragment start(SupportFragment fragment) // 以某種啟動模式,啟動新的Fragment start(SupportFragment fragment, int launchMode) // 啟動新的Fragment,並能接收到新Fragment的數據返回 startForResult(SupportFragment fragment,int requestCode) // 啟動目標Fragment,並關閉當前Fragment startWithFinish(SupportFragment fragment)
2、關閉Fragment:
// 關閉當前Fragment pop(); // 關閉某一個Fragment棧內之上的Fragments popTo(Class fragmentClass, boolean includeSelf); // 如果想出棧后,緊接着開始.beginTransaction()開始一個事務,請使用下面的方法: // 在 第二篇 文章內的 Fragment事務部分的問題 有解釋原因 popTo(Class fragmentClass, boolean includeSelf, Runnable afterTransaction)
3、在SupportFragment內,支持監聽返回按鈕事件:
@Override public boolean onBackPressedSupport() { // 返回false,則繼續傳遞返回事件; 返回true則不繼續傳遞 return false; }
4、 定義當前Fragment的動畫,復寫onCreateFragmentAnimation
方法:
@Override protected FragmentAnimator onCreateFragmentAnimation() { // 獲取在SupportActivity里設置的全局動畫對象 FragmentAnimator fragmentAnimator = _mActivity.getFragmentAnimator(); fragmentAnimator.setEnter(0); fragmentAnimator.setExit(0); return fragmentAnimator; // 也可以直接通過 // return new FragmentAnimator(enter,exit,popEnter,popExit)設置一個全新的動畫 }
5、獲取當前Activity/Fragment內棧頂(子)Fragment:
getTopFragment();
6、獲取棧內某個Fragment對象:
findFragment(Class fragmentClass);
// 獲取某個子Fragment對象 findChildFragment(Class fragmentClass);
更多
隱藏/顯示 輸入法:
// 隱藏軟鍵盤 一般用在onHiden里 hideSoftInput(); // 顯示軟鍵盤 showSoftInput(View view);
下面是DetailFragment startForResult
ModifyTitleFragment的代碼:
DetailFragment.class里:
startForResult(ModifyDetailFragment.newInstance(mTitle), REQ_CODE);
@Override public void onFragmentResult(int requestCode, int resultCode, Bundle data) { super.onFragmentResult(requestCode, resultCode, data); if (requestCode == REQ_CODE && resultCode == RESULT_OK ) { // 在此通過Bundle data 獲取返回的數據 } } ModifyTitleFragment.class里: Bundle bundle = new Bundle(); bundle.putString("title", "xxxx"); setFramgentResult(RESULT_OK, bundle);
下面是以一個singleTask模式start
一個Fragment的標准代碼:
HomeFragment fragment = findFragment(HomeFragment.class);
if (fragment == null) { fragment = HomeFragment.newInstance(); }else{ Bundle newBundle = new Bundle(); // 傳遞的bundle數據,會調用目標Fragment的onNewBundle(Bundle newBundle)方法 fragment.putNewBundle(newBundle); } // homeFragment以SingleTask方式啟動 start(fragment, SupportFragment.SINGLETASK); // 在HomeFragment.class中: @Override protected void onNewBundle(Bundle newBundle){ // 在此可以接收到數據 }
關於Fragmentation幫你恢復Fragment,你需要知道的
2個概念:
"同級"式:比如QQ的主界面,“消息”、“聯系人”、“動態”,這3個Fragment屬於同級關系
“流程”式:比如登錄->注冊/忘記密碼->填寫信息->跳轉到主頁Activity
對於Activity內的“流程”式Fragments(比如登錄->注冊/忘記密碼->填寫信息->跳轉到主頁Activity),Fragmentation幫助你處理了棧內的恢復,保證Fragment不會重疊,你不需要再自己處理了。
但是如果你的Activity內的Fragments是“同級”的,那么需要你復寫onHandleSaveInstanceState()
使用findFragmentByTag(tag)
或getFragments()
去恢復處理。
@Override protected void onHandleSaveInstancState(Bundle savedInstanceState) { // 復寫的時候 下面的super一定要刪掉 // super.onHandleSaveInstancState(savedInstanceState); // 在此處 通過findFragmentByTag或getFraments來恢復,詳情參考第二篇文章 }
而如果你有Fragment嵌套,那么不管是“同級”式還是“流程”式,你都需要自己去恢復處理。
原文鏈接:http://www.jianshu.com/p/38f7994faa6b
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。