Для реализации этой задачи на Jetpack Compose, нам необходимо создать состояние, которое будет храниться на основном экране и передаваться в диалоговое окно. Это обеспечит сохранение выбора между вызовами.
1. Подготовка состояний на основном экране
Чтобы диалоговое окно «помнило» предыдущий выбор, мы объявим переменную selectedOption на уровне экрана.
// Возможные варианты выбора
val options = listOf("Yearly", "Monthly", "Weekly")
// Состояние на главном экране
var showDialog by remember { mutableStateOf(false) }
var savedChoice by remember { mutableStateOf("") } // Текст для отображения на экране
var lastSelectedOption by remember { mutableStateOf<String?>(null) } // Для памяти диалога
2. Создание кастомного диалогового окна
@Composable
fun CustomChoiceDialog(
initialSelection: String?,
onDismiss: () -> Unit,
onConfirm: (String) -> Unit,
onCancel: () -> Unit
) {
// Внутреннее состояние окна для выбора (до нажатия кнопки Сохранить)
var currentSelection by remember { mutableStateOf(initialSelection) }
Dialog(onDismissRequest = onDismiss) {
Surface(
shape = RoundedCornerShape(28.dp),
color = Color.White,
modifier = Modifier.fillMaxWidth().padding(16.dp)
) {
Column(
modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Выберите из списка", style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 20.sp))
Spacer(modifier = Modifier.height(8.dp))
Text("Выберите формат отображения даты:", color = Color.Gray, fontSize = 14.sp)
Spacer(modifier = Modifier.height(20.dp))
// Список переключателей
options.forEach { option ->
val isSelected = currentSelection == option
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
.border(1.dp, if (isSelected) Color(0xFFE3F2FD) else Color.LightGray, RoundedCornerShape(12.dp))
.background(if (isSelected) Color(0xFFE3F2FD) else Color.Transparent, RoundedCornerShape(12.dp))
.clickable { currentSelection = option }
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(
selected = isSelected,
onClick = { currentSelection = option },
colors = RadioButtonDefaults.colors(selectedColor = Color(0xFF007BFF))
)
Text(text = option, style = TextStyle(fontWeight = FontWeight.Medium))
}
}
Spacer(modifier = Modifier.height(24.dp))
// Кнопки управления
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(12.dp)) {
OutlinedButton(
onClick = onCancel,
modifier = Modifier.weight(1.dp),
shape = RoundedCornerShape(12.dp),
border = BorderStroke(1.dp, Color(0xFF007BFF))
) {
Text("Отмена", color = Color(0xFF007BFF))
}
Button(
onClick = { currentSelection?.let { onConfirm(it) } },
modifier = Modifier.weight(1.dp),
shape = RoundedCornerShape(12.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF007BFF)),
enabled = currentSelection != null
) {
Text("Сохранить", color = Color.White)
}
}
}
}
}
}
3. Логика работы
Первое открытие: Поскольку lastSelectedOption изначально равен null, ни один переключатель не будет выбран при первом запуске.
Кнопка «Сохранить»:
1. Обновляет savedChoice (текст отобразится на экране под именем "Lucas Scott").
2. Обновляет lastSelectedOption (чтобы диалог «запомнил» выбор для следующего раза).
3. Закрывает окно.
Кнопка «Отмена»:
1. Закрывает окно.
2. Вызывает Toast.makeText(context, "Ничего не выбрано", Toast.LENGTH_SHORT).show().
4. Внешний вид на экране
В центре экрана под текстом «Выбрал отображение даты:» мы просто выводим нашу переменную:
Text(
text = savedChoice,
style = TextStyle(fontWeight = FontWeight.Bold, fontSize = 24.sp),
modifier = Modifier.padding(top = 40.dp)
)