Запуск камеры и снятие изображения не возвращает на экран, с которого я запустил её.

Вопросы и ответы

Я запускаю камеру, делаю снимок, затем сохраняю (или если отменяю), меня никогда не отправляют обратно на экран, с которого я её запустил.
Допустим, у меня есть главный экран и детальный экран. Если я запускаю это с главного экрана, всё работает хорошо, но запуск с детального экрана, похоже, возвращает меня обратно на главный экран.

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)
                        }
                    }
                )
            }
        )
    }
}

Ответ

Проблема, с которой вы столкнулись, связана с тем, что при запуске камеры и возвращении из нее приложение не возвращает вас на экран, с которого вы начали. Разберем решение этой проблемы, основываясь на вашем коде и предложениях по улучшению.

Причины проблемы

Когда вы запускаете камеру из подробного экрана, система может обрабатывать возврат к главному экрану, если не установлены правильные флаги для перемещения между экранами. Это может происходить из-за неправильной навигации или передачи состояния.

Решение проблемы

  1. Обработка состояния экрана: Перед тем как открыть камеру, вам может потребоваться передать состояние вашего текущего экрана, чтобы вы знали, куда вернуться. Вы можете использовать ViewModel для хранения состояния или использовать аргументы навигации.

  2. Настройка навигации: Проверьте, правильно ли настроены ваши экраны в навигации. Для этого можно использовать 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() после завершения действия камеры или выбора изображения вернет вас назад. Убедитесь, что все экраны правильно сконфигурированы, и ваш стек навигации управляется правильно.

Оцените материал
Добавить комментарий

Капча загружается...