底部導航欄

問題

如何實現(xiàn)常見應用中的底部導航欄的功能?


底部導航欄.png

回答

可以借助 BottomNavigationView 來實現(xiàn)這一效果。

效果

效果.gif

簡介

BottomNavigationView 是應用程序的標準底部導航欄,是 Material Design 3 導航規(guī)范、Material Design 2 底部導航規(guī)范 的實現(xiàn)。

應用于頂級頁面的導航,適用于 3 - 5 個菜單項的場景。

本文的說明不涉及角標 ( 圖標右上角顯示的數(shù)字 )。如有需要,BottomNavigation 可能會有所幫助。

步驟

  1. 添加 BottomNavigationView 所在庫的依賴。
dependencies {
...
implementation 'com.google.android.material:material:1.4.0'
...
}

如果 build 失敗,可能和項目與 material 庫的版本不匹配有關。

1.5.0 版本對應 Material Design 3, 要求 compileSdkVersiontargetSdkVersion 不低于 31 。其他版本的項目要求可以查閱 material-components-android/releases。

  1. 在 Activity 的 layout 文件中使用 BottomNavigationView 控件。
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_navigation_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:menu="@menu/navigation_view_menu_items" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  1. 第二步中,BottomNavigationViewapp:menu 屬性需要引用一個菜單資源,該菜單資源用于定義導航欄中菜單項的數(shù)量和樣式。創(chuàng)建 res/menu 目錄,在目錄下創(chuàng)建菜單文件。
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_menu_item_home"
        android:icon="@drawable/navigation_home"
        android:title="主頁" />

    <item
        android:id="@+id/navigation_menu_item_contact"
        android:icon="@drawable/navigation_contact"
        android:title="聯(lián)系人" />

    <item
        android:id="@+id/navigation_menu_item_mine"
        android:icon="@drawable/navigation_mine"
        android:title="我的" />

</menu>

上面的菜單文件中,定義了 3 個菜單項,每個菜單項包含 id, icon(圖標) 和title (標題) 三個屬性。

  1. 第三步中的 icon 屬性需要引用 drawable 資源,以“主頁”為例進行說明。創(chuàng)建 drawable 文件, 為選中和非選中狀態(tài)添加對應的圖標。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/navigation_home_selected" android:state_selected="true" />
    <item android:drawable="@drawable/navigation_home_default" android:state_selected="false" />
</selector>

itemdrawable屬性引用 png 之類的圖片即可。

navigation_home_default.png
navigation_home_selected.png

至此,底部導航欄的樣式就實現(xiàn)了。

  1. 創(chuàng)建“主頁”、“聯(lián)系人”和“我的” Fragment 和 layout 文件。當某個菜單項選中時,切換到對應的 Fragment。

  2. 在 Activity 的 layout 文件中使用 ViewPager2 控件。作為 3 個 Fragment 的容器,并控制它們的切換。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/main_fragment_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@id/main_navigation_bar"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_weight="1" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/main_navigation_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:menu="@menu/navigation_view_menu_items" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

創(chuàng)建 ViewPager2 的 Fragment 適配器。

public class FragmentAdapter extends FragmentStateAdapter {

  private final ArrayList<Fragment> fragments;

  public FragmentAdapter(@NonNull FragmentActivity fragmentActivity) {
    super(fragmentActivity);
    fragments = new ArrayList<>();
    fragments.add(new HomeFragment());
    fragments.add(new ContactFragment());
    fragments.add(new MineFragment());
  }

  @NonNull
  @Override
  public Fragment createFragment(int position) {
    return fragments.get(position);
  }

  @Override
  public int getItemCount() {
    return fragments.size();
  }

}

在 Activity 中為 ViewPager2 設置適配器。

public class BottomNavigationBarActivity extends AppCompatActivity {

  private NavigationActivityBottomNavigationBarBinding binding;

  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    int layoutId = R.layout.navigation_activity_bottom_navigation_bar;
    binding = DataBindingUtil.setContentView(this, layoutId);
    // 為 ViewPager2 設置適配器
    binding.mainFragmentContainer.setAdapter(new FragmentAdapter(this));
  }

}
  1. 在 Activity 中為 BottomNavigationView 控件添加菜單項選中事件監(jiān)聽器,當某一項選中后,ViewPager2 切換為對應的 Fragment。
private void setNavigationItemSelectedListener() {
    binding.mainNavigationBar.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
      @Override
      public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        String itemTitle = (String) item.getTitle();
        switch (itemTitle) {
          case "主頁": {
            binding.mainFragmentContainer.setCurrentItem(0);
          }
          break;
          case "聯(lián)系人": {
            binding.mainFragmentContainer.setCurrentItem(1);
          }
          break;
          case "我的": {
            binding.mainFragmentContainer.setCurrentItem(2);
          }
          break;
        }
        return true;
      }
    });
  }

禁用 ViewPager2 控件的滑動切換頁面功能,僅支持點擊底部導航欄的菜單項切換頁面。( 監(jiān)聽 ViewPager2 的頁面切換,設置 BottomNavigationView 的選中項亦可。類似于微信的效果,支持點擊和滑動兩種切換方式 )

@Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    int layoutId = R.layout.navigation_activity_bottom_navigation_bar;
    binding = DataBindingUtil.setContentView(this, layoutId);
    binding.mainFragmentContainer.setAdapter(new FragmentAdapter(this));

   // 禁用滑動切換頁面功能
    binding.mainFragmentContainer.setUserInputEnabled(false);

    setNavigationItemSelectedListener();
  }

參考資料

  1. 斌林誠上 : Android 底部導航欄 BottomNavigationView
  2. BottomNavigationView
  3. material design : bottom-navigation

代碼

XuMeng-0/android-study

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容