目次

04.ホーム画面の表示

ホーム画面でNavGraphを作成し、NavHostに登録します。
NavHostに登録することにより、Compose Navigationを使ってホーム画面を表示することができます。

:feature:depart:homeモジュールのnavigationディレクトリ(新規作成します)内にNavGraph(DepartHomeNavigation.kt)を作成します。


package jp.co.progress_llc.portal.feature.depart.home.navigation

import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import jp.co.progress_llc.portal.feature.depart.home.presentation.DepartHomeScreen

const val DEPART_HOME = "depart_home"

fun NavGraphBuilder.departNavigation() {
  composable(DEPART_HOME) {
    DepartHomeScreen()
  }
}

7行目
発車予定のホーム画面のNavGraph名を定義しています。
10行目~11行目
DepartHomeScreenNavGraphに登録しています。

:feature:depart:navigationモジュールのbuild.gradle.ktsにホーム画面モジュールへの依存を追記します。

   :
dependencies {
   :
  implementation(project(":feature:depart:home"))
}

4行目
ホーム画面モジュールへの依存を追記します。

追記後、『Sync Now』で内容をプロジェクトに反映させます。

:feature:departモジュールのbuild.gradle.ktsCompose Navigationの依存ライブラリを追記します。

   :
dependencies {
   :
  api(project(":feature:depart:navigation"))
}

4行目
ナビゲーションモジュールを:appに公開します。

追記後、『Sync Now』で内容をプロジェクトに反映させます。

DI(Hilt)への登録

:feature:departモジュールのdiディレクトリ(新規作成します)内にDepartNavGraphModule.ktを作成し、NavGraphDI(Hilt)に登録します。

package jp.co.progress_llc.portal.feature.depart.di

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dagger.multibindings.IntoSet
import androidx.navigation.NavGraphBuilder
import jp.co.progress_llc.portal.feature.depart.navigation.departNavigation

@Module
@InstallIn(SingletonComponent::class)
object DepartNavGraphModule {
  @Provides
  @IntoSet
  fun provideDepartNavGraph(): NavGraphBuilder.() -> Unit = { departNavigation() }
}

14行目~16行目
NavGraphを登録しています。

アプリの依存に発車予定機能の窓口モジュールを追加

発車予定画面はアプリのホーム画面から遷移してきますので、:appモジュールのbuild.gradle.ktsに発車予定機能の窓口モジュールへの依存を追記します。

   :
dependencies {
   :
  implementation(project(":feature:depart"))
   :
}

4行目
発車予定機能の窓口モジュールへの依存を追記します。

追記後、『Sync Now』で内容をプロジェクトに反映させます。

アプリで定義したナビゲーションのコンテナNavHostで使用するNavControllerLocalNavControllerに変更します。

DI(Hilt)@InfoSetNavGraphを登録する場合、DI(Hilt)が生成するSet注入関数のスコープとNavControllerのライフサイクルが一致せず、クラッシュする可能性があります。
NavHostControllerではなく、LocalNavControllerを使用することでライフサイクルを一致させます。

   :
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.CompositionLocalProvider
   :
val LocalNavController = compositionLocalOf<NavHostController> {
  error("No NavController provided")
}
   :
fun AppNavigation(
   :
) {
  NavHost(
    navController = navController,
    startDestination = startDestination
  ) {
    builders.forEach { it() }
  }
  CompositionLocalProvider(LocalNavController provides navController) {
    NavHost(
      navController = navController,
      startDestination = startDestination
    ) {
      builders.forEach { it() }
    }
  }
}

2行目~3行目
必要なimportを追記しています。
5行目~7行目
LocalNavControllerの定義を追記しています。
12行目~17行目
18行目~25行目に入れ替えます。
NavHostの定義をCompositionLocalProvider内に入れることにより、LocalNavControllernavControllerとして提供しています。

アプリのホーム画面にナビゲーションを追加

発車予定画面はホーム画面の列車アイコンから遷移してきますので、:appモジュールのHomeScreen.ktにナビゲーション(画面遷移)を追記します。

   :
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
   :
import jp.co.progress_llc.portal.feature.depart.navigation.DEPART_ROUTE
   :
fun HomeScreen (
  modifier: Modifier = Modifier
  modifier: Modifier = Modifier,
  navController: NavHostController
) {
   :
      IconButton(
        onClick = { },
        onClick = { navController.navigate(DEPART_ROUTE) },
   :
fun HomeScreenPreview() {
  AppTheme {
    HomeScreen()
    val navController = rememberNavController()
    HomeScreen(navController = navController)
  }
}

2行目~3行目
必要なimportを追加します。
5行目
発車予定画面のNavGraph名を定義している依存のimportを追加します。
8行目~10行目
HomeScreenの引数にNavHostControllerを追加します。
14行目~15行目
IconButtononClickに発車予定画面への画面遷移を追加します。
19行目~21行目
HomeScreenの引数にNavHostControllerが追加されたのでプレビュー表示にも追加します。

アプリのホーム画面のNavGraphにナビゲーションを追加

:appモジュールのHomeNavigation.ktにもナビゲーションを追加します。

   :
import jp.co.progress_llc.portal.feature.depart.navigation.departNavigation
   :
fun NavGraphBuilder.homeNavigation() {
  composable("home") {
    HomeScreen()
    val navController = LocalNavController.current
    HomeScreen(navController = navController)
  }
  departNavigation()
}

2行目
:feature:departモジュールのNavigationimportします。
6行目~8行目
HomeScreenの引数にLocalNavControllerを追加します。
10行目
:feature:departモジュールのNavGraphを追記して遷移できるようにします

エミュレーターでアプリケーションを実行して、画面遷移で発車予定のホーム画面が表示されることを確認します。