Android Basic with ComposeのUnit4で学んだことをまとめてみる - Navigation
はじめに
こんにちは、某SIerでSEをやっているnekorush14です。
この記事は絶賛再*n入門しているAndroid開発について、Google公式のLearning Courseを通して学んだことをアウトプットするシリーズです。
Jetpack Composeに関するCourseのUnit4で得た知見を話します。
前回の記事はこちら👇
今回はUnit4で2つ目のテーマとなるNavigationについてまとめます。
Navigation
-
Jetpack ComposeのNavigationは
NavigationComponent
を使用する -
Navigation Componentには以下の要素が含まれる
-
NavController
- スクリーン間のナビゲーションを担当する
-
NavGraph
- スクリーンで使用するComposableの関係ををマッピングする
-
NavHost
- 現在のComposableを表示するためのContainerとして機能するComposable
-
-
アプリケーション内の画面数は有限であり、そのルートの数も有限
-
enum class
を使用して定義する
-
-
NavHost
はnavController
、startDestination
、modifier
を引数に取る-
navController
はrememberNavController()
を使用してNavHostController
を取得できる -
startDestination
はアプリ起動時に表示するScreenとなるenum class SampleScreen(@StringRes val title: Int) { Start(title = R.string.app_name) } Scaffold ( // ... ) { innerPadding -> val navController = rememberNavController() NavHost( navController = navController, startDestination = SampleScreen.Start.Name, modifier = Modifier.padding(innerPadding) ) { // ナビゲーション先で表示するComposableを定義する } }
-
-
NavHost
のコンテンツ関数内で表示する画面のComposableを指定する-
composable()
関数を使用して指定する-
composable()
のroute
にenum class
のname
を指定してルーティングする
enum class SampleScreen(@StringRes val title: Int) { Start(title = R.string.app_name) } Scaffold ( // ... ) { innerPadding -> val navController = rememberNavController() NavHost( navController = navController, startDestination = SampleScreen.Start.Name, modifier = Modifier.padding(innerPadding) ) { // ナビゲーションのルーティングを定義する composable(route = SampleScreen.Start.name) { // 画面に表示するComposable本体を定義する SampleScreen() } } }
-
-
-
LocalContext.current
の参照-
Context
はAndroidシステムが提供する抽象クラス -
アプリケーション固有のリソース・クラスへのアクセス、Activityの起動などのコールが可能となる
// 現在実行中のアプリにおけるコンテキストを取得する val context = LocalContext.current // コンテキストの中から指定したリソースIDを持つ文字列を取得する val sampleText = context.resources.getString(R.strings.sample_text)
-
-
navController
を使う際、navController
のオブジェクトを渡すのではなくnavController.navigate()
をもつLambdaを関数ハンドラとして渡す -
前の画面に戻る場合には
navController.popBackStack
を使用する-
引数は
route
とinclusive
-
route
: 戻る先のルート文字列 -
inclusive
: 指定したルートもBackStackから削除するかを示すBool値、false
の場合、指定したルートは削除せずに他のルートをBackStackから削除する
@Composable fun SampleApp( viewModel: OrderViewModel = viewModel(), navController: NavHostController = rememberNavController() ) { // 引数で渡されたnavControllerのBackStackEntryを状態として保持する val backStackEntry by navController.currentBackStackEntryAsState() // 現在の画面をBackStackEntryから取得する // ここでは、BackStackEntryが何も無い場合に // Startで定義される画面を現在の画面とする val currentScreen = SampleScreen.valueOf( backStackEntry?.destination?.route ?: SampleScreen.Start.name ) Scaffold( topBar = { SampleAppBar( currentScreen = currentScreen, canNavigateBack = navController.previousBackStackEntry != null, navigateUp = { navController.navigateUp() } // TopBarの左上に表示される戻るボタンが押されたときのコールバック ) } ) { // ナビゲーションのルーティングを定義する composable(route = SampleScreen.Start.name) { // 画面に表示するComposable本体を定義する SampleScreen( // ... onNextButtonClicked = { // ここでnavController自体は渡さない viewModel.setQuantity(it) // 引数に指定した画面へ繊維する navController.navigate(SampleScreen.Detail.name) }, modifier = Modifier .fillMaxSize() .padding(dimensionResource(R.dimen.padding_medium)) ) } } }
-
-
-
ShareSheetなど別のアプリなどにナビゲートする場合は
navController
ではなくintent
を使用する -
NavHost
を使用せずに、if/else
等によって分岐する場合、自前でバックボタンの挙動を実装する-
androidx.activity.compose.BackHandler
を使用する-
BackHandler {}
内でConfiguration Changeが発生し、ReCompositionが発生するようなアクションを実行する
import androidx.activity.compose.BackHandler @Composable fun SampleHomeScreen( sampleUiState: SampleUiState, onTabPressed: (SampleType) -> Unit, onSampleCardPressed: (Int) -> Unit, onDetailScreenBackPressed: () -> Unit, modifier: Modifier = Modifier ) { // ... // ここでは、UiStateが持つフラグで表示内容を変化させる if (sampleUiState.isShowingHomepage) { SampleAppContent( sampleUiState = sampleUiState, onTabPressed = onTabPressed, onSampleCardPressed = onSampleCardPressed, navigationItemContentList = navigationItemContentList, modifier = modifier ) } else { SampleDetailsScreen( sampleUiState = sampleUiState, onBackPressed = onDetailScreenBackPressed, modifier = modifier ) } } @Composable fun SampleDetailScreen( sampleUiState: SampleUiState, onBackPressed: () -> Unit, modifier: Modifier = Modifier ) { // BackHandlerを使用して自前の"戻る"処理を定義する BackHandler { onBackPressed() // 引数で渡された"戻る"処理を実行する } // ... } // ...
-
-
まとめ
今回はAndroidのNavigationについて簡単にまとめてみました。
思っていたよりもシンプルに実装できることがわかったので、今後のアプリ制作などでも活用していきたいです。
また、NavHost
を使用せずにwhen
などの分岐で表示するComposableを変更するなど、いくつか実装方法があることを学びました。
実装するアプリによって適切なNavigationの実装は変化すると感じました。
次回はAdaptive Layoutの話をします。
Discussion