Android Studio

ユーザーからの入力を受け取って、次の画面に渡す機能を実装

ユーザーからの入力を受け取って、次の画面に渡す機能を実装

今回は以下のことを行います。

  • 最初の画面(FirstScreen)に TextField を設置し、ユーザーが名前を入力できるようにする。
  • 入力された名前を保持するための状態変数(MutableState)を定義する。
  • ボタンを押して2番目の画面に遷移する際に、入力された名前を引数として渡す。
  • 2番目の画面(SecondScreen)で、受け取った名前を表示する。

具体的な手順

MainActivity.kt ファイルを編集していきます。

1. 必要なimportを追加

ファイルの先頭あたりに、以下を追加してください。(既にあるものもあるかもしれません)

import androidx.compose.material3.TextField // テキスト入力欄用
import androidx.compose.runtime.rememberSaveable // TextFieldの状態保持用
import androidx.compose.ui.text.input.TextFieldValue // TextFieldの値の型

2. FirstScreen を修正して TextField を追加し、名前を渡す

FirstScreen 関数を以下のように変更します。

@OptIn(ExperimentalMaterial3Api::class) // TextFieldで必要になる可能性
@Composable
fun FirstScreen(navController: NavController, modifier: Modifier = Modifier) {
    // 入力された名前を保持する状態変数
    // rememberSaveableは、画面回転などでも状態を保持するために使う
    var nameInput by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }

    Column(
        modifier = modifier.fillMaxSize().padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            text = "あなたの名前を入力してください:",
            modifier = Modifier.padding(bottom = 8.dp)
        )

        TextField(
            value = nameInput, // 現在の値
            onValueChange = { newValue -> nameInput = newValue }, // 値が変更されたときの処理
            label = { Text("名前") }, // ヒントテキスト
            singleLine = true, // 1行入力
            modifier = Modifier
                .fillMaxWidth() // 幅いっぱいに広げる
                .padding(bottom = 24.dp)
        )

        Button(onClick = {
            // 入力された名前を取得
            val name = nameInput.text
            // 名前をURLエンコードして遷移先に渡す
            // 日本語などの特殊文字が含まれる場合はURLエンコードが必要
            val encodedName = java.net.URLEncoder.encode(name, "UTF-8")
            navController.navigate("second_screen/$encodedName")
        }) {
            Text("2番目の画面へ")
        }
    }
}
  • rememberSaveable { mutableStateOf(TextFieldValue(“”)) }: TextField の入力内容を保持するための状態変数です。rememberSaveable を使うことで、画面回転などでも入力内容が失われにくくなります。TextFieldValue.Saver を指定しているのは、TextFieldValue 型を正しく保存するためです。
  • TextField(value = nameInput, onValueChange = { … }): テキスト入力欄です。value に現在の状態を、onValueChange に入力が変更されたときの処理を指定します。
  • java.net.URLEncoder.encode(name, “UTF-8”): 日本語の名前などがURLの一部として渡される際に、正しくエンコードされるようにします。

3. SecondScreen を修正して受け取った名前を表示する

SecondScreen 関数を以下のように変更します。

@Composable
fun SecondScreen(navController: NavController, name: String?) { // nameを引数で受け取る
    Column(
        modifier = Modifier.fillMaxSize().padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        // 受け取った名前を表示
        val displayText = if (name.isNullOrBlank()) "名無しさん" else name
        Text(text = "こんにちは、$displayText さん!", modifier = Modifier.padding(bottom = 24.dp))
        Text(text = "これは2番目の画面です!", modifier = Modifier.padding(bottom = 24.dp))

        Button(onClick = { navController.popBackStack() }) {
            Text("最初の画面に戻る")
        }
    }
}
  • name: String?: 画面遷移から渡された名前を受け取ります。? はnull許容を表し、名前が渡されなかった場合(ありえないはずですが、念のため)に備えます。
  • if (name.isNullOrBlank()) “名無しさん” else name: 受け取った名前が空だった場合に「名無しさん」と表示する簡単なロジックです。

4. NavHost のルーティング定義を修正する

MainActivity の setContent ブロック内の NavHost 定義を修正し、second_screen ルートが名前の引数を受け取るようにします。

@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourAppNameTheme {
                val navController = rememberNavController()

                Scaffold(
                    topBar = {
                        TopAppBar(title = { Text("名前入力アプリ") })
                    }
                ) { paddingValues ->
                    NavHost(
                        navController = navController,
                        startDestination = "first_screen",
                        modifier = Modifier.padding(paddingValues)
                    ) {
                        composable("first_screen") {
                            // FirstScreenにはnavControllerのみ渡す
                            FirstScreen(navController = navController)
                        }
                        // second_screenのルート定義に名前の引数を追加
                        composable("second_screen/{name}") { backStackEntry ->
                            val name = backStackEntry.arguments?.getString("name") // 名前を受け取る
                            SecondScreen(navController = navController, name = name)
                        }
                    }
                }
            }
        }
    }
}
  • composable(“second_screen/{name}”): {name} を追加することで、このルートが name という引数を受け取ることを宣言します。
  • backStackEntry.arguments?.getString(“name”): backStackEntry から引数として渡された名前を取得します。

これで、アプリを再実行して、名前を入力し、ボタンを押すと、次の画面で入力した名前が表示されるはずです!

※Google AI Studioによる回答を参考にしました

目次に戻る