androidkotlinandroid-jetpack-composeandroid-camerax

CameraX with jetpack composes screen logic


I have this page where I have a button that opens a camera preview and I want it to have a exit button to simply exit the camera preview and continue where I left off on the page:

class page : Screen {
    @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
    @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
    @Composable
    override fun Content() {
        val scrollState = rememberScrollState()
        val navigator = LocalNavigator.currentOrThrow
        var showCameraPreview by remember { mutableStateOf(false) }
        val pictureList = mutableListOf<ImageBitmap>()

        Scaffold(
            topBar = { },
            bottomBar = { },
            content = {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .verticalScroll(scrollState)
                        .padding(it)
                ) {
                    //Page content

                    Button(onClick = { showCameraPreview = true }) {
                        Text(text = "Open Camera")
                    }
                }
            }
        )
        if (showCameraPreview) {
            CameraContent()
        }
    }
}

The CameraContent composable:

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
fun CameraContent() {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val cameraController = remember { LifecycleCameraController(context) }
    Scaffold(
        modifier = Modifier.fillMaxSize(),
        floatingActionButton = { },
        floatingActionButtonPosition = FabPosition.Center,
    ) { paddingValues: PaddingValues ->
        Box {
            AndroidView(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues),
                factory = { context ->
                    PreviewView(context).apply {
                        layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
                        setBackgroundColor(Color.BLACK)
                        scaleType = PreviewView.ScaleType.FILL_START
                    }.also { previewView ->
                        previewView.controller = cameraController
                        cameraController.bindToLifecycle(lifecycleOwner)
                    }
                })
            //Exit out button
            Button(
                onClick = { //Here i want to exit out of camera }) {
                    Icon(
                        imageVector = Icons.Default.Close,
                        contentDescription = "Close the camera",
                    )
                }
            )
        }
    }
}

I have tried cameraController.unbind() but that just freezes the page.


Solution

  • You can pass a lambda to the CameraContent composable:

    @Composable
    fun CameraContent(closeCamera: () -> Unit) {
        //rest of the screen
        
        //Exit out button
        Button(onClick = closeCamera) {
            Icon(
                 imageVector = Icons.Default.Close,
                 contentDescription = "Close the camera"
            )
        }
    }
    

    Then in your Content Screen where you have

    if (showCameraPreview) {
        CameraContent()
    }
    

    call the closeCamera lambda:

    if (showCameraPreview) {
        CameraContent() {
            showCameraPreview = false
        }
    }