Чтобы подсистема работала, нам нужно не просто нарисовать кнопочки, а связать их логикой навигации и валидации.
Я разделю процесс на 3 четких этапа: создание структуры, настройка регистрации и настройка входа.
Этап 1: Подготовка фундамента (Навигация)
Чтобы передать данные из SignUp в LoginIn, нам нужен NavController. В Jetpack Compose это делается через NavHost. Мы определим два маршрута.
- signup: экран регистрации.
- login/{email}/{password}: экран входа, который «ждет» на вход почту и пароль.
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "signup") {
composable("signup") {
SignUpScreen(navController)
}
composable(
route = "login/{email}/{password}",
arguments = listOf(
navArgument("email") { defaultValue = "" },
navArgument("password") { defaultValue = "" }
)
) { backStackEntry ->
val email = backStackEntry.arguments?.getString("email")
val pass = backStackEntry.arguments?.getString("password")
LoginInScreen(navController, email, pass)
}
}
Этап 2: Создание SignUp.kt
1. Переменные состояния (State)
Для каждого поля создаем mutableStateOf. Это «память» экрана.
var login by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var confirmPassword by remember { mutableStateOf("") }
var isChecked by remember { mutableStateOf(false) }
// Переменные для хранения текстов ошибок
var loginError by remember { mutableStateOf<String?>(null) }
var emailError by remember { mutableStateOf<String?>(null) }
var passError by remember { mutableStateOf<String?>(null) }
2. Применяем ограничения
Теперь «научим» кнопку проверять условия из задания:
- Логин: login.length >= 8
- Email: email.length >= 12 && email.contains("@")
- Пароль: KeyboardOptions(keyboardType = KeyboardType.Number) и длина >= 8.
- Совпадение: password == confirmPassword.
Пример:
Button(
onClick = {
// Сбрасываем ошибки перед проверкой
loginError = if (login.length < 8) "Минимум 8 символов" else null
emailError = if (email.length < 12 || !email.contains("@")) "Минимум 12 знаков и @" else null
passError = if (password.length < 8) "Минимум 8 цифр" else if (password != confirmPassword) "Пароли не совпадают" else null
// Если всё чисто и чекбокс нажат — летим на экран логина
if (loginError == null && emailError == null && passError == null && isChecked) {
navController.navigate("login/$email/$password")
}
},
// Кнопка визуально блокируется, если поля пусты или чекбокс не нажат
enabled = login.isNotEmpty() && email.isNotEmpty() && isChecked
) {
Text("Зарегистрироваться")
}
Этап 3: Создание LoginIn.kt
Здесь мы реализуем требования по отображению пароля и автоподстановке.
1. Автоматическая вставка
Мы принимаем initialEmail и initialPass из навигации и сразу кладем их в state.
@Composable
fun LoginInScreen(navController: NavController, initialEmail: String?, initialPass: String?) {
var email by remember { mutableStateOf(initialEmail ?: "") }
var password by remember { mutableStateOf(initialPass ?: "") }
// Переменная для переключения "глазика"
var isPasswordVisible by remember { mutableStateOf(false) }
2. Реализация отображения пароля
Используем параметр visualTransformation в OutlinedTextField.
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Пароль") },
// Если true — текст виден, если false — заменяется точками
visualTransformation = if (isPasswordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { isPasswordVisible = !isPasswordVisible }) {
val icon = if (isPasswordVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff
Icon(imageVector = icon, contentDescription = null)
}
}
)
3. Ограничения экрана Login
Тут проверка проще, но она обязательна.
Button(
onClick = {
if (email.isEmpty() || password.isEmpty()) {
// Показываем Toast или текст ошибки: "Все поля обязательны"
} else if (!email.contains("@")) {
// Ошибка: "Email должен содержать @"
} else {
// Успешный вход
}
}
) {
Text("Войти")
}