完成形(OutlinedTextField をクリックすると日付選択ができるようにする)
- 日付を選択すると OutlinedTextField の値を変更する
- 日付選択はダイアログから行う
- テキスト入力はさせない
- 日付選択のダイアログを閉じると OutlinedTextField のフォーカスを外す
実装
OutlinedTextFiled 全体を選択可能にする
【NG】 Modifier.fillMaxWidth().clickable(onClick)
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = { /* TODO */ }),
value = value,
onValueChange = onValueChange,
placeholder = { Text(text = "選択してください") },
trailingIcon = {
Icon(
imageVector = GeneratedVectorImages.IcnPull,
contentDescription = null,
)
},
)
OutlinedTextField 全体に対してクリックしようと Modifier.fillMaxWidth().clickable(onClick)
をしてもクリックできませんので注意が必要です。
ポイント
- interactionSource を設定する
- readOnly = true を設定する
@Composable
fun SelectOutlineTextField(
value: String,
onValueChange: (String) -> Unit,
onClick: () -> Unit,
) {
val interactionSource = remember {
object : MutableInteractionSource {
override val interactions = MutableSharedFlow<Interaction>(
extraBufferCapacity = 16,
onBufferOverflow = BufferOverflow.DROP_OLDEST,
)
override suspend fun emit(interaction: Interaction) {
when (interaction) {
is PressInteraction.Press -> {
onClick()
}
}
interactions.emit(interaction)
}
override fun tryEmit(interaction: Interaction): Boolean {
return interactions.tryEmit(interaction)
}
}
}
OutlinedTextField(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
value = value,
onValueChange = onValueChange,
placeholder = { Text(text = "選択してください") },
trailingIcon = {
Icon(
imageVector = Icons.Filled.KeyboardArrowDown,
contentDescription = null,
)
},
readOnly = true,
interactionSource = interactionSource,
)
}
日付選択画面
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DatePickerModal(
onDateSelected: (Long?) -> Unit,
onDismiss: () -> Unit
) {
val datePickerState = rememberDatePickerState()
DatePickerDialog(
onDismissRequest = onDismiss,
confirmButton = {
TextButton(onClick = {
onDateSelected(datePickerState.selectedDateMillis)
onDismiss()
}) {
Text("OK")
}
},
dismissButton = {
TextButton(onClick = onDismiss) {
Text("Cancel")
}
}
) {
DatePicker(state = datePickerState)
}
}
完成形
@Composable
fun HomeScreen() {
var dateText by remember { mutableStateOf("") }
var showDialog by remember { mutableStateOf(false) }
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
SelectOutlineTextField(
value = dateText,
onValueChange = { dateText = it },
onClick = { showDialog = true },
)
}
val focusManager = LocalFocusManager.current
if (showDialog) {
DatePickerModal(
onDateSelected = {
dateText = convertMillisToDate(it)
showDialog = false
focusManager.clearFocus()
},
onDismiss = {
showDialog = false
focusManager.clearFocus()
},
)
}
}
private fun convertMillisToDate(millis: Long?): String {
val formatter = SimpleDateFormat("MM/dd/yyyy", Locale.getDefault())
return millis?.let {
formatter.format(Date(it))
} ?: ""
}
参考資料