今天給大家介紹一個開源庫,看完後,很多 fragment 以及狀態列相關的煩惱將離你而去。
我不喜歡囉嗦,讓我們直入主題吧。
搞定 fragment 那些事
fragment 有哪些煩惱?
動畫不正常,尤其是有 fragment 巢狀的時候?
can not perform this action after onSaveInstanceState 異常?
不正常的重影?
煩人的生命週期?
不知道用哪個 fragmentManager?
AndroidNavigation 來拯救世界
建議分別在 Android 4.4、5.0 和 6.0 下體驗
一行程式碼實現 Fragment 巢狀,一次性構建好巢狀層級
AndroidNaviation 提供了幾款常用的容器來幫助我們快速實現 fragment 巢狀,分別是 DrawerFragment, TabBarFragment, NavigationFragment
看名字不難理解,DrawerFragment 為我們提供了抽屜的能力,是一個很拉風的抽屜哦,當開啟時,狀態列會自動隱藏。
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/1618bd0d05be787d14093bc5bd9d4bf0442d9a7e1083a705f8ba189f280d1fc1.gif)
相信我,你們的設計師會喜歡的。
TabBarFragment 為我們提供了 BottomNavigationBar 選項卡的能力,譬如微信、支付寶主頁面底部都會有一個
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/98734b8d39ffbc60f2504f5975c66672fb86865217ec11a8474e0f0fdadcf8c0.gif)
NavigationFragment 則以棧的形式管理它的子 fragment, 並且提供了轉場動畫。巢狀在 NavigationFragment 裡面的子 fragment 會受到祝福,擁有自動建立 Toolbar 的能力,並在恰當的時機自動新增返回按鈕。
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/80b013ec07b466da5251179cc24aab7d8968b88e1567d4d82bb48abaf6de8e7d.gif)
如果一個應用的主頁面,既有 drawer 也有 tabs,每個 tab 的頁面還要能切換到其它頁面,看起來很複雜的巢狀吧。但 AndroidNavigation 可以一次性就把這些 UI 層級構建好
// MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
// 首頁
HomeFragment homeFragment = new HomeFragment();
NavigationFragment homeNavigatoinFragment = new NavigationFragment();
homeNavigationFraggment.setRootFragment(homeFragment);
homeNavigatoinFragment.setTabBarItem(new TabBarItem(R.drawable.icon_home, "首頁"));
// 通訊錄
ContactsFragment contactsFragment = new ContactsFragment();
NavigationFragment contactsNavigationFragment = new NavigationFragment();
contactsNavigationFragment.setRootFragment(contactsFragment);
contactsNavigationFragment.setTabBarItem(new TabBarItem(R.drawable.icon_contacts, "通訊錄"));
// 新增 tab 到 TabBarFragment
TabBarFragment tabBarFragment = new TabBarFragment();
tabBarFragment.setFragments(homeNavigatoinFragment, contactsNavigationFragment);
// drawer
DrawerFragment drawerFragemnt = new DrawerFragment();
MenuFragment menuFragment = new MenuFragment();
drawerFragment.setMenuFragment(menuFragment);
drawerFragment.setContentFragment(tabBarFragment);
drawerFragment.setMaxDrawerWidth(300); // 設定 menu 的最大寬度
// 把 DrawerFragment 設定為 Activity 的根
setRootFragment(drawerFragemnt);
}
}
複製程式碼
就這樣,我們把上面提到的 UI 層級構建好了,一共有四層 fragment 巢狀哦,恐怖不恐怖,興奮不興奮?
這些容器還不能滿足你的需求?自定義容器!
我們的 ViewPagerFragment 就是個自定義容器
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/2eabf54cd73f940eabc735cfb97fd0f2b8fbe6ece5f2728cd2ec5188cd6cb961.gif)
核心程式碼
// ViewPagerFragemnt.java
int location;
@Override
public boolean isParentFragment() {
return true;
}
@Override
protected int preferredStatusBarColor() {
int[] colors = new int[] {Color.RED, Color.GREEN, Color.BLUE};
return colors[location];
}
private void initView(View view) {
AppBarLayout appBarLayout = view.findViewById(R.id.appbar_layout);
// important
if(isStatusBarTranslucent()) {
appendStatusBarPadding(appBarLayout, -2);
}
}
複製程式碼
並不複雜
一行程式碼實現 Fragment 跳轉,不再需要寫一大堆操作 fragment 的程式碼了,不用擔心用錯 FragmentManager 了
所有的 fragment 都具備兩個基本的導航能力 presentFragment 以及 dismissFragment,就是開啟和關閉一個 fragment
// HomeFragment.java
presentFragment(new TargetFragment(), REQUEST_CODE);
複製程式碼
一行程式碼就跳過去了
帶上個請求碼,TargetFragment 在關閉前可以通過 setResult 返回結果給前一個頁面
Bundle result = new Bundle();
result.putString("text", resultEditText.getText().toString());
setResult(Activity.RESULT_OK, result);
dismissFragment();//關閉
複製程式碼
如果 fragemnt 巢狀在 NavigationFragment 中,會有更多的導航能力, 比如
- push 入棧一個介面
- pop 出棧一個介面
- popTo 同時出棧多個介面到指定介面,而且不用擔心一次出棧多個介面,動畫會有問題
對上面這些導航不滿意?自定義導航!
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/17bfcedbc9915266c03813b96a6c178ff51cc2275050fdbfb19f1a9edf990d0d.gif)
具體實現參考 demo 中 GridFragment 這個類
懶載入
AndroidNavigation 提供了兩個生命週期函式來幫助我們實現懶載入
protected void onViewAppear();
protected void onViewDisappear();
複製程式碼
搞定狀態列那些事
狀態列的煩事有哪些?
沉浸式以及沉浸式帶來的 BUG ?
白底黑字但結果 5.0 以下全是白的?
想要將沉浸式以及狀態列顏色相容到 4.4?
啥,鍵盤不頂用了?
一行程式碼開關沉浸式狀態列,相容到 Android 4.4 並解決了相關 BUG
// 開啟沉浸式
setStatusBarTranslucent(true);
複製程式碼
![一個輪子搞定 Fragment 和狀態列那些事](https://i.iter01.com/images/4b72cfe98dae4c93c7ab9c99b8e8c9544adce9265f2252d4a6d5a97628f4f916.gif)
其它諸如狀態列顏色,只需要有選擇性地重寫以下方法,返回期待的結果即可
// 狀態列字型風格,黑或白
protected BarStyle preferredStatusBarStyle();
// 是否隱藏狀態列
protected boolean preferredStatusBarHidden();
// 狀態列顏色
protected int preferredStatusBarColor();
// 切換狀態列顏色時,是否平滑過渡
protected boolean preferredStatusBarColorAnimated();
複製程式碼
就是這麼簡單
關於 AndroidNavigation 更多功能更詳細的描述,請看這裡 README
喜歡的話記得給顆星星,因為要集齊 100 顆才可以召喚神龍。