BottomNavigationView + Fragment 底部導航欄實現
本篇是自己在學習 BottomNavigationView
時整理的筆記。
效果圖:

效果圖.gif
目錄結構:

目錄結構.png
ofollow,noindex">https://github.com/Evan-zch/BottomNavigationViewDemo
正文
前面呈現的效果圖是現在很多主流App都在使用底部導航欄模式,比如常用的微信、QQ這些基本的社交軟體,其實要實現上面的效果也很簡單。
1、佈局檔案
<android.support.design.widget.BottomNavigationView android:id="@+id/bv_bottomNavigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@color/write" app:itemIconTint="@drawable/bottom_navigation_item_selector" app:itemTextColor="@drawable/bottom_navigation_item_selector" app:menu="@menu/main_bottom_navigation" />
要使用 BottomNavigationView
需要在build.gradle中新增 design
庫
implementation 'com.android.support:design:27.1.1'
app:itemBackground
:設定item的背景
app:itemIconTint
:設定icon的顏色
app:itemTextColor
:設定文字的顏色
app:menu
:設定底部導航欄icon和文字
2、 bottom_navigation_item_selector.xml
app:itemIconTint="@drawable/bottom_navigation_item_selector"
app:itemTextColor="@drawable/bottom_navigation_item_selector"
在 drawable
下新建 xml
檔案,通過為 itemIconTint
和 itemTextColor
設定 selector
,可實現在點選時 icon
和 title
顏色的變換。
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/theme" android:state_checked="true" /> <item android:color="@color/bottom_navigation_normal" android:state_checked="false" /> </selector>
3、 main_bottom_navigation.xml
app:menu="@menu/main_bottom_navigation"
在 menu
目錄下新建 xml
檔案,自定義底部導航欄 icon
及 title
,程式碼如下:
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/menu_message" android:enabled="true" android:icon="@mipmap/message" app:showAsAction="ifRoom" android:title="訊息" /> <item android:id="@+id/menu_contacts" android:enabled="true" android:icon="@mipmap/icon_contacts" app:showAsAction="ifRoom" android:title="聯絡人" /> <item android:id="@+id/menu_discover" android:enabled="true" android:icon="@mipmap/icon_discover" app:showAsAction="ifRoom" android:title="發現" /> <item android:id="@+id/menu_me" android:enabled="true" app:showAsAction="ifRoom" android:icon="@mipmap/me" android:title="我" /> </menu>
4、在Activity中進行初始化:
public void initBottomNavigation() { mBottomNavigationView = findViewById(R.id.bv_bottomNavigation); // 新增監聽 mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.menu_message: setFragmentPosition(0); break; case R.id.menu_contacts: setFragmentPosition(1); break; case R.id.menu_discover: setFragmentPosition(2); break; case R.id.menu_me: setFragmentPosition(3); break; default: break; } // 這裡注意返回true,否則點選失效 return true; } }); }
特別說明
當底部導航欄 item
數目大於三個時,展示效果如下:

item大於三個時效果圖.gif
當 item
數目大於三個時,底部導航欄展示的效果採取動畫的方式,很多時候非我們想要的效果, 通過反射來進行處理 原文 。
程式碼如下:
public class BottomNavigationViewHelper { @SuppressLint("RestrictedApi") public static void disableShiftMode(BottomNavigationView view) { BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0); try { Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode"); shiftingMode.setAccessible(true); shiftingMode.setBoolean(menuView, false); shiftingMode.setAccessible(false); for (int i = 0; i < menuView.getChildCount(); i++) { BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i); //noinspection RestrictedApi item.setShiftingMode(false); // set once again checked value, so view will be updated //noinspection RestrictedApi item.setChecked(item.getItemData().isChecked()); } } catch (NoSuchFieldException e) { Log.e("BNVHelper", "Unable to get shift mode field", e); } catch (IllegalAccessException e) { Log.e("BNVHelper", "Unable to change value of shift mode", e); } } }
可以在初始化的時候多新增一行程式碼就能避免這個問題
mBottomNavigationView = findViewById(R.id.bv_bottomNavigation); // 解決當item大於三個時,非平均佈局問題 BottomNavigationViewHelper.disableShiftMode(mBottomNavigationView);