#android-jetpack #android-jetpack-compose
Вопрос:
Как отображать сообщения об ошибках для нескольких текстовых полей в jetpack compose. только с одним полем:
private var isError by mutableStateOf(false)
private fun validate(text: String){
isError = if(text.isEmpty()){
true
}else{
android.util.Patterns.EMAIL_ADDRESS.matcher(text).matches()
}
Log.i("Boolean",isError.toString())
}
TextField(value = email,placeholder = { Text(text = "E-mail")},
onValueChange = {
email=it
isError = false
},
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
singleLine = true,
isError = isError,
keyboardActions = KeyboardActions { validate(email) },
modifier=Modifier.align(Alignment.CenterHorizontally),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
leadingIcon = { Icon(imageVector = Icons.Default.Email, contentDescription = null) })
У меня есть форма со множеством текстовых полей, как мне проверить одно за другим. например, если у меня есть два поля с именем и электронной почтой. Я думал о том, чтобы сделать цикл со всеми полями, но я не знаю, является ли это лучшей практикой. Кто-нибудь может мне помочь
var nome by rememberSaveable{ mutableStateOf("")}
var email by rememberSaveable{ mutableStateOf("") }
TextField(value = nome,placeholder = { Text(text = "Nome")},
onValueChange = {
nome=it
},
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
modifier=Modifier.align(Alignment.CenterHorizontally),
leadingIcon = { Icon(imageVector = Icons.Default.Person, contentDescription = null) })
Spacer(modifier = Modifier.padding(5.dp))
TextField(value = email,placeholder = { Text(text = "E-mail")},
onValueChange = {
email=it
},
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
),
modifier=Modifier.align(Alignment.CenterHorizontally),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
leadingIcon = { Icon(imageVector = Icons.Default.Email, contentDescription = null) })
Spacer(modifier = Modifier.padding(5.dp))
Button(
onClick = { verifyEmpty(strings=validate) },
colors = ButtonDefaults.buttonColors(
contentColor = colorResource(id = R.color.marron),
backgroundColor = colorResource (id = R.color.pastel_green)
),
) {
Text(text = stringResource(id = R.string.view_cad),
color= colorResource(id = R.color.marron))
}
Ответ №1:
Когда у вас так много общего между двумя представлениями, пришло время перенести это в отдельную композицию. Вы можете указать все различия в параметрах и не повторять одни и те же настройки для каждого представления.
Я предлагаю вам создать класс состояния для вашего пользовательского текстового поля. Я сохраню текст, текст ошибки и логику валидатора. Таким образом, вы можете позвонить проверить, когда вам нужно: по нажатию кнопки или по кнопке готово на клавиатуре:
@Composable
fun TestView(
) {
val nomeState = rememberErrorTextFieldState("", validate = { text ->
when {
text.isEmpty() -> {
"text.isEmpty()"
}
else -> null
}
})
val emailState = rememberErrorTextFieldState("", validate = { text ->
when {
text.isEmpty() -> {
"text.isEmpty()"
}
!android.util.Patterns.EMAIL_ADDRESS.matcher(text).matches() -> {
"pattern doesn't match"
}
else -> null
}
})
Column {
ErrorTextField(
state = nomeState,
placeholderText = "nome",
leadingIconVector = Icons.Default.Person,
modifier = Modifier.align(Alignment.CenterHorizontally),
)
ErrorTextField(
state = emailState,
placeholderText = "email",
leadingIconVector = Icons.Default.Email,
modifier = Modifier.align(Alignment.CenterHorizontally),
)
Button(
onClick = {
listOf(nomeState, emailState).forEach(ErrorTextFieldState::validate)
},
) {
Text(text = "stringResource(id = R.string.view_cad)")
}
}
}
@Composable
fun ErrorTextField(
state: ErrorTextFieldState,
placeholderText: String,
leadingIconVector: ImageVector,
modifier: Modifier,
) {
Column {
val error = state.error
TextField(
value = state.text,
onValueChange = { state.updateText(it) },
placeholder = { Text(text = placeholderText) },
shape = RoundedCornerShape(8.dp),
colors = TextFieldDefaults.textFieldColors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
errorCursorColor = Color.Red
),
singleLine = true,
isError = error != null,
leadingIcon = { Icon(imageVector = leadingIconVector, contentDescription = null) },
keyboardActions = KeyboardActions {
state.validate()
},
modifier = modifier,
)
if (error != null) {
Text(
error,
color = Color.Red,
)
}
}
}
@Composable
fun rememberErrorTextFieldState(
initialText: String,
validate: (String) -> String? = { null },
): ErrorTextFieldState {
return rememberSaveable(saver = ErrorTextFieldState.Saver(validate)) {
ErrorTextFieldState(initialText, validate)
}
}
class ErrorTextFieldState(
initialText: String,
private val validator: (String) -> String?,
) {
var text by mutableStateOf(initialText)
private set
var error by mutableStateOf<String?>(null)
private set
fun updateText(newValue: String) {
text = newValue
error = null
}
fun validate() {
error = validator(text)
}
companion object {
fun Saver(
validate: (String) -> String?,
) = androidx.compose.runtime.saveable.Saver<ErrorTextFieldState, String>(
save = { it.text },
restore = { ErrorTextFieldState(it, validate) }
)
}
}
Комментарии:
1. Я последовал вашему примеру, но как проявляется ошибка? или просто установите для isError значение false или true? Я использую compose_version = ‘1.0.0-rc01’
2. Когда я нажимаю «Ввод» в текстовом поле, он выдает ошибку с этим кодом, если(ошибка){ Текст(текст = «сообщение об ошибке») } но как это работает при нажатии кнопки
3. @RafaelSouza Я пропустил, что вам нужна эта кнопка, обновил свой ответ. Также вы можете обновить до «1.0.1», он был выпущен некоторое время назад
4. Привет, Филип, функция сохранения выдает следующую ошибку :
Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly
5. @StefanoSansone, Вероятно, с тех пор что-то изменилось =) Я обновил свой ответ