Skip to content

Instantly share code, notes, and snippets.

@FStranieri
Last active December 10, 2021 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FStranieri/d5b91d8d840b7ce696ae3035d792be04 to your computer and use it in GitHub Desktop.
Save FStranieri/d5b91d8d840b7ce696ae3035d792be04 to your computer and use it in GitHub Desktop.
ML Composer - Ep.1 - Main Composable
@Composable
private fun BuildCameraUI() {
//PERMISSION MANAGEMENT part
...
{
ConstraintLayout(Modifier.fillMaxSize()) {
val (preview, takePhotoButton, progress) = createRefs()
val executor = remember(context) { ContextCompat.getMainExecutor(context) }
val imageCapture: MutableState<ImageCapture?> = remember { mutableStateOf(null) }
MLCameraView(
modifier = Modifier.constrainAs(preview) {
linkTo(top = parent.top, bottom = parent.bottom)
linkTo(start = parent.start, end = parent.end)
width = Dimension.fillToConstraints
height = Dimension.fillToConstraints
}, // Occupy the max size in the Compose UI tree
imageCapture = imageCapture,
context = context,
executor = executor
)
Button(modifier = Modifier.constrainAs(takePhotoButton) {
linkTo(start = parent.start, end = parent.end)
bottom.linkTo(parent.bottom, 16.dp)
width = Dimension.preferredWrapContent
height = Dimension.preferredWrapContent
}, onClick = {
imageCapture.value?.takePicture(executor,
object : ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
textRecognitionViewModel.scan(
CameraUtils.convertImageProxyToBitmap(
image,
context as Activity
)
)
}
override fun onError(exception: ImageCaptureException) {
Toast.makeText(context, exception.message, Toast.LENGTH_LONG)
.show()
}
})
})
{
Text(stringResource(R.string.camera_scan_button))
}
val isLoading = remember { textRecognitionViewModel.getLoadingProgress() }
CircularProgressIndicator(
modifier = Modifier
.constrainAs(progress) {
linkTo(top = parent.top, bottom = parent.bottom)
linkTo(start = parent.start, end = parent.end)
width = Dimension.value(80.dp)
height = Dimension.value(80.dp)
}
.then(Modifier.alpha(if (isLoading.value) 1f else 0f)),
)
}
}
}
//CAMERA COMPOSABLE
@Composable
fun MLCameraView(
modifier: Modifier,
imageCapture: MutableState<ImageCapture?>,
executor: Executor,
context: Context
) {
val previewCameraView = remember { PreviewView(context) }
val cameraProviderFuture =
remember(context) { ProcessCameraProvider.getInstance(context) }
val cameraProvider = remember(cameraProviderFuture) { cameraProviderFuture.get() }
val lifecycleOwner = LocalLifecycleOwner.current
AndroidView(
modifier = modifier,
factory = {
cameraProviderFuture.addListener(
{
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
imageCapture.value = ImageCapture.Builder().build()
cameraProvider.unbindAll()
val prev = Preview.Builder().build().also {
it.setSurfaceProvider(previewCameraView.surfaceProvider)
}
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector as CameraSelector,
imageCapture.value,
prev
)
}, executor
)
previewCameraView
}
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment