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



今回は以下のことを行います。
- 最初の画面(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による回答を参考にしました
