BottomNavigationView 的使用及遇到的坑

BottomNavigationView 使用

  • 佈局中設置
<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    style="@style/Widget.Design.BottomNavigationView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_gravity="bottom"
    android:background="@color/viewBackground"
    app:elevation="@dimen/dp_16"
    app:itemIconTint="@drawable/nav_item_color_state"
    app:itemTextColor="@drawable/nav_item_color_state"
    app:menu="@menu/bottom_navigation_main" />
複製代碼
  • BottomNavigationView 是經過 menu 來設置 item
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_home"
        android:enabled="true"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/home"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_knowledge_system"
        android:enabled="true"
        android:icon="@drawable/ic_apps_black_24dp"
        android:title="@string/knowledge_system"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_wechat"
        android:enabled="true"
        android:icon="@drawable/ic_wechat_black_24dp"
        android:title="@string/wechat"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_navigation"
        android:enabled="true"
        android:icon="@drawable/ic_navigation_black_24dp"
        android:title="@string/navigation"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_project"
        android:enabled="true"
        android:icon="@drawable/ic_project_black_24dp"
        android:title="@string/project"
        app:showAsAction="ifRoom" />
</menu>
複製代碼
  • Activity 中使用
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bottom_navigation);
    BottomNavigationView navigation = (BottomNavigationView)findViewById(R.id.bottom_navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}

private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_home:
                return true;
            case R.id.action_knowledge_system:
                return true;
            case R.id.action_wechat:
                return true;
            case R.id.action_navigation:
                return true;
            case R.id.action_project:
                return true;
        }
        return false;
    }
};
複製代碼

使用時遇到的坑

坑一:使用時 item 個數大於 3 個時會有位移動畫,那麼如何設置底部圖標和字體都顯示並去掉點擊動畫?
  • 使用下面的類經過反射能夠修改
public class BottomNavigationViewHelper {
    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);
        }
    }
}
複製代碼
BottomNavigationViewHelper.disableShiftMode(navigation);
複製代碼

另:在support版本 28 如下(不包含)使用上面的方法完美解決,那麼在support版本 28 以上怎麼解決呢?java

support 28 版本官方重構了 BottomNavigationView ,經過查閱 BottomNavigationViewBottomNavigationMenuView 中的代碼能夠知道經過設置 labelVisibilityMode 的顯示模式來設置底部圖標和字體都顯示並去掉點擊動畫。android

因此目前 support 版本 28 能夠使用下面的方法能夠完美解決:bash

java代碼中app

bottom_navigation.setLabelVisibilityMode(1);
複製代碼

或者 xml 佈局文件中ide

app:labelVisibilityMode="labeled"
複製代碼
坑二:如何實現中間的 icon 的樣式和其餘的不同?
  • app:menu="@menu/bottom_navigation_main" 指向的 bottom_navigation_main 修改成
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_home"
        android:enabled="true"
        android:icon="@drawable/ic_home_black_24dp"
        android:title="@string/home"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_knowledge_system"
        android:enabled="true"
        android:icon="@drawable/ic_apps_black_24dp"
        android:title="@string/knowledge_system"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_wechat"
        android:enabled="true"
        android:icon="@null"
        android:title=""
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_navigation"
        android:enabled="true"
        android:icon="@drawable/ic_navigation_black_24dp"
        android:title="@string/navigation"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_project"
        android:enabled="true"
        android:icon="@drawable/ic_project_black_24dp"
        android:title="@string/project"
        app:showAsAction="ifRoom" />
</menu>
複製代碼

也就是中間第三個 item 不設置圖標和文字。佈局

  • 而後在修改佈局文件(用一個 LinearLayout 中間設個一個 ImageView 覆蓋在 BottomNavigationView 上便可)
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:clipToPadding="true">

    <android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        style="@style/Widget.Design.BottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_gravity="bottom"
        android:background="@color/viewBackground"
        app:elevation="@dimen/dp_16"
        app:itemIconTint="@drawable/nav_item_color_state"
        app:itemTextColor="@drawable/nav_item_color_state"
        app:menu="@menu/bottom_navigation_main" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:elevation="16dp">

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2" />

        <ImageView
            android:id="@+id/navigation_center_image"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:padding="5dp"
            android:src="@mipmap/ic_launcher" />

        <View
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2" />

    </LinearLayout>
</FrameLayout>
複製代碼
坑三:選中 item 時,item 的文本會有一個動畫,icon 也會上移一點,那麼如何取消動畫呢?
  • 下面的參數是 item 選中和沒有選中的文本大小,把它們設置成同樣的就沒有動畫了。
design_bottom_navigation_active_text_size
design_bottom_navigation_text_size
複製代碼
  • 下面的參數是 iconmargin_bottom 值,能夠調整它讓 icon 垂直居中。
design_bottom_navigation_margin
複製代碼
  • 把下面的根據須要複製到項目的 dimen.xml 文件中便可。
<!--BottomNavigationView 的選中沒有選中的字體大小-->
<dimen name="design_bottom_navigation_active_text_size">10sp</dimen>
<dimen name="design_bottom_navigation_text_size">10sp</dimen>

<!--BottomNavigationView 只放圖標時的設置-->
<dimen name="design_bottom_navigation_active_text_size">0sp</dimen>
<dimen name="design_bottom_navigation_text_size">0sp</dimen>
<dimen name="design_bottom_navigation_margin">16dp</dimen>
複製代碼
相關文章
相關標籤/搜索