Compose 表单处理完全指南:验证、状态管理与最佳实践

2024-05-26 · 26 min · 表单处理

表单是应用中最常见的交互形式之一。从简单的登录表单到复杂的多步骤注册流程,正确处理表单状态和验证是构建良好用户体验的关键。

一、表单状态管理

data class LoginFormState(
    val email: String = "",
    val password: String = "",
    val rememberMe: Boolean = false
)

@Composable
fun LoginForm() {
    var formState by remember { mutableStateOf(LoginFormState()) }
    
    OutlinedTextField(
        value = formState.email,
        onValueChange = { formState = formState.copy(email = it) },
        label = { Text("邮箱") }
    )
}

二、表单验证

data class FormField(
    val value: String = "",
    val error: String? = null
)

class FormValidator {
    fun validateEmail(email: String): String? {
        return when {
            email.isBlank() -> "邮箱不能为空"
            !Patterns.EMAIL_ADDRESS.matcher(email).matches() -> "邮箱格式不正确"
            else -> null
        }
    }
    
    fun validatePassword(password: String): String? {
        return when {
            password.isBlank() -> "密码不能为空"
            password.length < 8 -> "密码至少8个字符"
            else -> null
        }
    }
}

三、ViewModel 集成

class LoginViewModel : ViewModel() {
    private val _formState = MutableStateFlow(LoginFormState())
    val formState = _formState.asStateFlow()
    
    fun onEmailChange(email: String) {
        _formState.update { it.copy(email = email) }
    }
    
    fun submit() {
        viewModelScope.launch {
            // 验证并提交
        }
    }
}

四、焦点管理

@Composable
fun FormWithFocus() {
    val focusManager = LocalFocusManager.current
    
    OutlinedTextField(
        value = username,
        onValueChange = { username = it },
        keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next),
        keyboardActions = KeyboardActions(
            onNext = { focusManager.moveFocus(FocusDirection.Down) }
        )
    )
}

五、多步骤表单

enum class Step { ACCOUNT, PERSONAL, PREFERENCES }

@Composable
fun MultiStepForm() {
    var currentStep by remember { mutableStateOf(Step.ACCOUNT) }
    
    when (currentStep) {
        Step.ACCOUNT -> AccountStep()
        Step.PERSONAL -> PersonalStep()
        Step.PREFERENCES -> PreferencesStep()
    }
    
    Button(onClick = { /* 下一步 */ }) {
        Text("下一步")
    }
}

六、最佳实践

总结