Open1

3.ナビゲーション

るるすたるるすた

最初の画面作成

アプリを起ち上げたときに表示される画面を作る。
完璧でなくてもいい。とりあえずの見本品。

@Composable
fun HomeScreen(
    modifier: Modifier = Modifier,
    onNavigateToDrill: () -> Unit = {},
    onNavigateToDrawing: () -> Unit = {},
    onNavigateToProfile: () -> Unit = {},
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(dimensionResource(R.dimen.p_medium)),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        //タイトル画面
        Image(
            painter = painterResource(R.drawable.rakugakicho),
            contentDescription = null,
        )
        Spacer(modifier = Modifier.padding(dimensionResource(R.dimen.p_medium)))
        //計算ドリルボタン
        Button(
            onClick = onNavigateToDrill,
            modifier = Modifier.fillMaxWidth(),
        ){
            Row {
                Text(text = Screen.Drill.emoji())
                Spacer(modifier = Modifier.width(dimensionResource(R.dimen.p_medium)))
                Text(text = stringResource(R.string.drill_jp))
            }
        }
        Spacer(modifier = Modifier.padding(dimensionResource(R.dimen.p_medium)))

        //らくがきちょうボタン
        Button(
            onClick = onNavigateToDrawing,
            modifier = Modifier.fillMaxWidth(),
        ){
            Row {
                Text(text = Screen.Drawing.emoji())
                Spacer(modifier = Modifier.width(dimensionResource(R.dimen.p_medium)))
                Text(text = stringResource(R.string.drawing_jp))
            }
        }
        Spacer(modifier = Modifier.padding(dimensionResource(R.dimen.p_medium)))

        //ぷろふぃーるボタン
        Button(
            onClick = onNavigateToProfile,
            modifier = Modifier.fillMaxWidth(),
        ){
            Row {
                Text(text = Screen.Profile.emoji())
                Spacer(modifier = Modifier.width(dimensionResource(R.dimen.p_medium)))
                Text(text = stringResource(R.string.profile_jp))
            }
        }
    }
}

依存関係追加

navigation用のライブラリを追加していきます。
ついでにテスト用のも追加。
(2025年5月24日時点の最新)

build.gradle.kts

dependencies {
    implementation(libs.androidx.navigation.compose)            //navigation
    androidTestImplementation(libs.androidx.navigation.testing)   //navigationTest
    //省略

libs.versions.toml

[versions]

navigation-compose = "2.9.0"
navigationTesting = "2.9.0"

[libraries]

androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation-compose" }
androidx-navigation-testing = { module = "androidx.navigation:navigation-testing", version.ref = "navigationTesting" }

sync nowする

navigationフォルダとファイル作成

ファイルの位置はuiの下にnavigationフォルダを作り、この中にNavGraph.ktを作る。
やっと赤枠とか美しく描けるようになった💦

Screenクラス作成(任意)

画面の名前や専用アイコン等を一意に関する用のシールドクラスを作成。
作っても作らなくてもいい。
作っておくと後が楽。

sealed class Screen(
    val route:String,           //ルートの名前
    val displayNameRes: Int,    //画面の名前
    val icon: ImageVector       //画面のアイコン
) {
    object Home: Screen("home",R.string.home_jp, Icons.Filled.Home)
    object Drill: Screen("drill",R.string.drill_jp, Icons.Filled.Calculate)
    object DrillSelect: Screen("drillSelect",R.string.drill_jp, Icons.Filled.Calculate)
    object Drawing: Screen("drawing",R.string.drawing_jp, Icons.Filled.Palette)
    object Profile: Screen("profile",R.string.profile_jp, Icons.Filled.Person)

    /***引数を渡すための設定
     * ex)profile/1234のような引数を作るときに
     *  navController.navigate(Screen.Profile.routeWithArgs("1234"))と書く
     */
    fun routeWithArgs(vararg args: String): String {
        return buildString {
            append(route)
            args.forEach { arg ->
                append("/$arg")
            }
        }
    }
}

NavGraph作成

ファイルの位置はuiの下にnavigationフォルダを作り、この中にNavGraph.ktを作る。
やっと赤枠とか美しく描けるようになった💦

まだ画面作っていないので、エラーになるところはコメント化。

@Composable
fun NoToreNavGraph(navController:NavHostController) {
    NavHost(
        navController = navController,
        startDestination = Screen.Home.route    //最初の画面
    ){
        composable(Screen.Home.route) {
            HomeScreen(
                onNavigateToDrill = { navController.navigate(Screen.Drill.route) },
                onNavigateToDrawing = { navController.navigate(Screen.Drawing.route) },
                onNavigateToProfile = { navController.navigate(Screen.Profile.route) }
            )
        }
        composable(Screen.Drill.route) {
//            DrillScreen()
        }
        composable(Screen.Drawing.route) {
//            DrawingScreen()
        }
        composable(Screen.Profile.route) {
//            ProfileScreen()
        }
    }
}
NavHostのインポート

import androidx.navigation.compose.NavHost

App画面でNavGraphを設定

NoTreNavGraphはBoxでラップ。
Box使うのはtopBarとかの領域(innerPadding)確保のため。

@Composable
fun NoToreApp() {
    val navController = rememberNavController()
    
    Scaffold(
        //topBar
        //bottomBar
    ) { innerPadding ->
        Box(modifier=Modifier.padding(innerPadding)){
            NoToreNavGraph(navController = navController)
        }
    }
}