Я запускаю камеру, делаю снимок, затем сохраняю (или если отменяю), меня никогда не отправляют обратно на экран, с которого я её запустил.
Допустим, у меня есть главный экран и детальный экран. Если я запускаю это с главного экрана, всё работает хорошо, но запуск с детального экрана, похоже, возвращает меня обратно на главный экран.
fun AttachmentImageCameraButton(
viewModel: IDumpViewModel,
isEnabled: Boolean,
resetFocus: () -> Unit = {}
) {
val context = LocalContext.current
val dump by viewModel.dump.collectAsState()
val remainingAttachments = max(0, Constants.MAX_NUMBER_ATTACHMENTS - dump.attachments.size)
var showDialog by remember { mutableStateOf(false) }
val multiplePhotoPicker = rememberLauncherForActivityResult(
contract = if (remainingAttachments > 1) {
ActivityResultContracts.PickMultipleVisualMedia(maxItems = remainingAttachments)
} else {
ActivityResultContracts.PickVisualMedia()
},
) { uris ->
if (uris is List<*>) {
uris.forEach { uri ->
if (uri is Uri) viewModel.addImageAttachment(uri)
}
} else if (uris is Uri) {
viewModel.addImageAttachment(uris)
}
resetFocus()
viewModel.toggleAttachmentMenu(false)
}
val cameraLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.TakePicturePreview()
) { bitmap: Bitmap? ->
bitmap?.let {
viewModel.addCameraImageAttachment(it)
}
resetFocus()
viewModel.toggleAttachmentMenu(false)
}
val requestPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
cameraLauncher.launch(null)
} else {
Toast.makeText(context, "Отсутствует разрешение на использование камеры", Toast.LENGTH_SHORT).show()
}
}
NavButton(
onClick = {
showDialog = true
},
icon = Icon.Camera,
isEnabled = isEnabled,
)
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
confirmButton = {
AlertDialogOption(
option = "Выбрать из Галереи",
onClick = {
showDialog = false
multiplePhotoPicker.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
)
},
dismissButton = {
AlertDialogOption(
option = "Использовать Камеру",
onClick = {
showDialog = false
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
cameraLauncher.launch(null)
} else {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
)
}
)
}
}
Ответ
Проблема, с которой вы столкнулись, связана с тем, что при запуске камеры и возвращении из нее приложение не возвращает вас на экран, с которого вы начали. Разберем решение этой проблемы, основываясь на вашем коде и предложениях по улучшению.
Причины проблемы
Когда вы запускаете камеру из подробного экрана, система может обрабатывать возврат к главному экрану, если не установлены правильные флаги для перемещения между экранами. Это может происходить из-за неправильной навигации или передачи состояния.
Решение проблемы
-
Обработка состояния экрана: Перед тем как открыть камеру, вам может потребоваться передать состояние вашего текущего экрана, чтобы вы знали, куда вернуться. Вы можете использовать
ViewModel
для хранения состояния или использовать аргументы навигации. - Настройка навигации: Проверьте, правильно ли настроены ваши экраны в навигации. Для этого можно использовать
NavController
для управления стеком навигации.
Изменение кода
Примерно как вы можете изменить свой код:
// Добавьте NavController в параметры функции
fun AttachmentImageCameraButton(
navController: NavController,
viewModel: IDumpViewModel,
isEnabled: Boolean,
resetFocus: () -> Unit = {}
) {
val context = LocalContext.current
val dump by viewModel.dump.collectAsState()
val remainingAttachments = max(0, Constants.MAX_NUMBER_ATTACHMENTS - dump.attachments.size)
var showDialog by remember { mutableStateOf(false) }
// Навигатор
val navController = rememberNavController()
val multiplePhotoPicker = rememberLauncherForActivityResult(
contract = if (remainingAttachments > 1) {
ActivityResultContracts.PickMultipleVisualMedia(maxItems = remainingAttachments)
} else {
ActivityResultContracts.PickVisualMedia()
},
) { uris ->
if (uris is List<*>) {
uris.forEach { uri ->
if (uri is Uri) viewModel.addImageAttachment(uri)
}
} else if (uris is Uri) {
viewModel.addImageAttachment(uris)
}
resetFocus()
viewModel.toggleAttachmentMenu(false)
navController.popBackStack() // Возврат назад
}
val cameraLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.TakePicturePreview()
) { bitmap: Bitmap? ->
bitmap?.let {
viewModel.addCameraImageAttachment(it)
}
resetFocus()
viewModel.toggleAttachmentMenu(false)
navController.popBackStack() // Возврат назад
}
val requestPermissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
cameraLauncher.launch(null)
} else {
Toast.makeText(context, "Недостаточно прав на использование камеры", Toast.LENGTH_SHORT).show()
}
}
NavButton(
onClick = {
showDialog = true
},
icon = Icon.Camera,
isEnabled = isEnabled,
)
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
confirmButton = {
AlertDialogOption(
option = "Выбрать из Галереи",
onClick = {
showDialog = false
multiplePhotoPicker.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
)
},
dismissButton = {
AlertDialogOption(
option = "Использовать Камеру",
onClick = {
showDialog = false
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
cameraLauncher.launch(null)
} else {
requestPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
)
}
)
}
}
Резюме
Это решение должно помочь вам вернуться на экран, с которого вы запустили камеру, независимо от того, запущена ли она из главного экрана или из подробного экрана. Использование navController.popBackStack()
после завершения действия камеры или выбора изображения вернет вас назад. Убедитесь, что все экраны правильно сконфигурированы, и ваш стек навигации управляется правильно.