ボトムナビゲーションとタブ
BottomNavigationViewをNavControllerに接続して複数セクションのナビゲーションを実装し、TabLayout、ViewPager2、TabLayoutMediatorでスワイプ可能なタブを作成します。
「ボトムナビゲーションとタブ」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン5/5です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全5レッスンが含まれています。
ナビゲーションパターン
Androidアプリのトップレベルナビゲーションでよく使われる2つのパターンです:
- Bottom Navigation — 3~5個の主要な遷移先に使用します。常に表示されます。重要度が同じセクション(例:ホーム、検索、プロフィール)に最適です。
- Tabs — 1つの画面内にある関連コンテンツ(例:すべて/進行中/完了)に使用します。スワイプ操作に対応するため、ViewPager2と組み合わせることがよくあります。
BottomNavigationViewのレイアウト
ActivityのレイアウトにBottomNavigationViewとFragmentContainerViewを追加します:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
</LinearLayout>ボトムナビゲーションのメニュー項目
res/menu/bottom_nav_menu.xmlで項目を定義します。各項目のIDは、ナビゲーショングラフの遷移先IDと一致させる必要があります:
<!-- res/menu/bottom_nav_menu.xml -->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/homeFragment"
android:icon="@drawable/ic_home"
android:title="Home" />
<item
android:id="@+id/searchFragment"
android:icon="@drawable/ic_search"
android:title="Search" />
<item
android:id="@+id/profileFragment"
android:icon="@drawable/ic_person"
android:title="Profile" />
</menu>NavControllerへの接続
onCreate()でBottomNavigationViewをNavControllerに接続します:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHost = supportFragmentManager
.findFragmentById(R.id.navHostFragment) as NavHostFragment
val navController = navHost.navController
binding.bottomNav.setupWithNavController(navController)
// Hide bottom nav on detail screens:
navController.addOnDestinationChangedListener { _, destination, _ ->
binding.bottomNav.visibility = when (destination.id) {
R.id.detailFragment -> View.GONE
else -> View.VISIBLE
}
}
}
}ボトムナビゲーションのバッジ
ボトムナビゲーションの項目に通知バッジを表示します:
// Show a numbered badge:
val badge = binding.bottomNav.getOrCreateBadge(R.id.homeFragment)
badge.number = 5
badge.isVisible = true
// Show dot badge (no number):
val dotBadge = binding.bottomNav.getOrCreateBadge(R.id.searchFragment)
dotBadge.isVisible = true
// Remove badge:
binding.bottomNav.removeBadge(R.id.homeFragment)TabLayout
TabLayoutは横方向のタブを表示します。通常は、スワイプ可能なコンテンツを表示するためにViewPager2と組み合わせて使用します:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>ViewPager2 + FragmentStateAdapter
各タブの位置に対応するフラグメントを提供するアダプターを作成します:
class TasksPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
override fun getItemCount() = 3
override fun createFragment(position: Int): Fragment = when (position) {
0 -> AllTasksFragment()
1 -> ActiveTasksFragment()
2 -> CompletedTasksFragment()
else -> throw IllegalStateException("Unknown tab $position")
}
}TabLayoutMediator
TabLayoutMediatorでViewPager2とTabLayoutを接続します:
// In Fragment.onViewCreated():
val adapter = TasksPagerAdapter(this)
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = when (position) {
0 -> "All"
1 -> "Active"
2 -> "Done"
else -> ""
}
}.attach()
// Disable swipe if needed:
binding.viewPager.isUserInputEnabled = falseアイコン付きタブ
TabLayoutのタブにアイコンを追加します:
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
when (position) {
0 -> {
tab.text = "Home"
tab.setIcon(R.drawable.ic_home)
}
1 -> {
tab.text = "Search"
tab.setIcon(R.drawable.ic_search)
}
2 -> {
tab.text = "Profile"
tab.setIcon(R.drawable.ic_person)
}
}
}.attach()オフスクリーンページの上限
デフォルトでは、ViewPager2は隣接するページだけをメモリに保持します。切り替えた後もタブを保持したい場合は、offscreenPageLimitを増やします:
// Keep 2 pages on each side alive:
binding.viewPager.offscreenPageLimit = 2
// Note: FragmentStateAdapter saves and restores state for off-screen
// fragments even when offscreenPageLimit is 1 (default).
// Only increase this when you need views (not just state) to survive.ボトムナビゲーションとタブの選び方
適切なパターンを選ぶための簡単な指針です:
- Bottom Navigationを使用する:目的の異なるトップレベルの遷移先が3~5個ある場合(ホーム、検索、通知、プロフィール)
- Tabsを使用する:同じ種類のコンテンツを絞り込んだり分類したりする場合(すべて/進行中/アーカイブ済みのタスク)
- 両方を組み合わせる:トップレベルのセクションにはBottom Navを使用し、セクション内の絞り込みにはTabsを使用します
確認問題
TabLayoutをViewPager2に接続し、タブのラベルを設定するクラスはどれですか?
まとめ:ボトムナビゲーションとタブ
複数セクションのナビゲーションを正しく実装する方法:
- BottomNavigationView — 重要度が同じ3~5個の遷移先。メニューIDはナビゲーショングラフの遷移先IDと一致させます
setupWithNavController()— タブの自動切り替えとバックスタックgetOrCreateBadge()によるバッジ- TabLayout + ViewPager2 — 同じコンテンツをスワイプして切り替えられる絞り込み表示
TabLayoutMediator— 2つを接続し、ラベルを設定します
次は、コードの信頼性を保つためのJUnitによるユニットテストです。
よくある質問
「ボトムナビゲーションとタブ」レッスンは無料ですか?
はい。「ボトムナビゲーションとタブ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全5レッスンが含まれています。
「ボトムナビゲーションとタブ」で何を学びますか?
BottomNavigationViewをNavControllerに接続して複数セクションのナビゲーションを実装し、TabLayout、ViewPager2、TabLayoutMediatorでスワイプ可能なタブを作成します。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Android Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン5/5です。
「ボトムナビゲーションとタブ」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAndroid Academyレッスンでコードを書いて実行できますか?
はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Material Designの基礎
- テーマとスタイル
- カスタムView
- アニメーションとトランジション
- ボトムナビゲーションとタブ