Open1

TextFieldの汎用化

るるすたるるすた

なぜ汎用化なのか?

今回はこんなUIを考えました。

  • 1行目:タイトル
  • 2行目:入力例
  • 3行目:入力するところ
  • 4行目:スペース

これをコンポーザブル関数にすると。。。

@Composable
fun TestScreen(
    modifier: Modifier = Modifier,
){
    Text(text = "■表情", style= MaterialTheme.typography.titleLarge)
    Text(text = "例)ぷんぷん怒っている")
    TextField(
        value = uiState.personState.emotion,
        onValueChange = { viewModel.updateUiState({ copy(personState = personState.copy(emotion = it)) }) },
        label = { Text(text=stringResource(R.string.person_emotion)) },
        modifier = modifier.fillMaxWidth()
    )
    Spacer(modifier = Modifier.height(dimensionResource(R.string.person_emotion)))
}

これ1つだけだったら問題ないと思います。
でも同じようなコンポーザブルが30個とかあったら。。。?
コピペするのもいいかなとは思いますが、後で2行目と3行目を入れ替えよう!とかスペースいらね!みたいな変更があった時に、「あ~~~~~~めんどくせ!」となります。
なので、汎用化して1個修正したら全部に適用!としておきます。

個別部分を引数にする

以下プログラムのうち、個別になる部分を決めていきます。
太字部分がそれにあたります。
Text(text = "■表情", style= MaterialTheme.typography.titleLarge)
Text(text = "例)ぷんぷん怒っている")
TextField(
value = uiState.personState.emotion,
onValueChange = { viewModel.updateUiState({ copy(personState = personState.copy(emotion = it)) }) },
label = { Text(text=stringResource(R.string.person_emotion)) },
modifier = modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(dimensionResource(R.string.person_emotion)))

変数化すると、こう

    Text(text = "■$title", style= MaterialTheme.typography.titleLarge)
    Text(text = "例)$example")
    TextField(
        value = value,
        onValueChange = onValueChange,
        label = { Text(text=stringResource(labelResId)) },
        modifier = modifier.fillMaxWidth()
    )
    Spacer(modifier = Modifier.height(dimensionResource(R.dimen.p_medium)))

新しい関数を作って、変数部分を引数に割り当てます。

@Composable
fun LabeledTextField(
    modifier: Modifier = Modifier,
+    title:String,
+    example:String,
+    value: String,
+    onValueChange: (String) -> Unit,
+    labelResId:Int,
){
    Text(text = "■$title", style= MaterialTheme.typography.titleLarge)
    Text(text = "例)$example")
    TextField(
        value = value,
        onValueChange = onValueChange,
        label = { Text(text=stringResource(labelResId)) },
        modifier = modifier.fillMaxWidth()
    )
    Spacer(modifier = Modifier.height(dimensionResource(R.dimen.p_medium)))
}

UIからの呼び出し

@Composable
fun TestScreen(
    modifier: Modifier = Modifier,
){
    LabeledTextField(
        title = "■表情",
        example = "ぷんぷん怒っている",
        value = uiState.personState.emotion,
        onValueChange = { viewModel.updateUiState({ copy(personState = personState.copy(emotion = it)) }) },
        labelResId = R.string.person_emotion,
    )
}

UI側では、引数に値を割り当てるだけになったので、設定も楽ですね!