CameraScreen: set up a Preview to make it easier to work on the layout

This commit is contained in:
Pierre-Yves Nicolas
2025-06-09 14:40:42 +02:00
parent 271f047c9d
commit d9a03c7131

View File

@@ -69,7 +69,6 @@ import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@@ -82,6 +81,7 @@ import org.mydomain.myscan.LiveAnalysisState
import org.mydomain.myscan.MainViewModel import org.mydomain.myscan.MainViewModel
import org.mydomain.myscan.Point import org.mydomain.myscan.Point
import org.mydomain.myscan.scaledTo import org.mydomain.myscan.scaledTo
import org.mydomain.myscan.ui.theme.MyScanTheme
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
@@ -99,7 +99,6 @@ fun CameraScreen(
val showPageDialog = rememberSaveable { mutableStateOf(false) } val showPageDialog = rememberSaveable { mutableStateOf(false) }
val isProcessing = rememberSaveable { mutableStateOf(false) } val isProcessing = rememberSaveable { mutableStateOf(false) }
val pageToValidate by viewModel.pageToValidate.collectAsStateWithLifecycle() val pageToValidate by viewModel.pageToValidate.collectAsStateWithLifecycle()
val pageCount = viewModel.pageCount()
val context = LocalContext.current val context = LocalContext.current
val requestPermissionLauncher = rememberLauncherForActivityResult( val requestPermissionLauncher = rememberLauncherForActivityResult(
@@ -122,11 +121,16 @@ fun CameraScreen(
} }
} }
Box(modifier = modifier.fillMaxSize()) { CameraScreenContent(
CameraPreviewWithOverlay(onImageAnalyzed, captureController, liveAnalysisState) modifier,
MessageBox(liveAnalysisState.inferenceTime) cameraPreview = {
CaptureButton( CameraPreview(
onClick = { onImageAnalyzed = onImageAnalyzed,
captureController = captureController
) },
pageCount = viewModel.pageCount(),
liveAnalysisState,
onCapture = {
showPageDialog.value = true showPageDialog.value = true
isProcessing.value = true isProcessing.value = true
captureController.takePicture( captureController.takePicture(
@@ -141,13 +145,8 @@ fun CameraScreen(
} }
) )
}, },
modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 96.dp) onFinalizePressed = onFinalizePressed
) )
CameraScreenFooter(
pageCount = pageCount,
onFinalizePressed = onFinalizePressed,
modifier = Modifier.align(Alignment.BottomCenter))
}
if (showPageDialog.value) { if (showPageDialog.value) {
PageValidationDialog( PageValidationDialog(
@@ -167,6 +166,33 @@ fun CameraScreen(
} }
} }
@Composable
private fun CameraScreenContent(
modifier: Modifier,
cameraPreview: @Composable () -> Unit,
pageCount: Int,
liveAnalysisState: LiveAnalysisState,
onCapture: () -> Unit,
onFinalizePressed: () -> Unit
) {
Box(modifier = modifier.fillMaxSize()) {
CameraPreviewWithOverlay(cameraPreview, liveAnalysisState)
MessageBox(liveAnalysisState.inferenceTime)
CaptureButton(
onClick = onCapture,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 96.dp)
)
CameraScreenFooter(
pageCount = pageCount,
onFinalizePressed = onFinalizePressed,
modifier = Modifier.align(Alignment.BottomCenter)
)
}
}
@Composable @Composable
fun CaptureButton(onClick: () -> Unit, modifier: Modifier) { fun CaptureButton(onClick: () -> Unit, modifier: Modifier) {
val color = MaterialTheme.colorScheme.primary val color = MaterialTheme.colorScheme.primary
@@ -199,8 +225,7 @@ fun CaptureButton(onClick: () -> Unit, modifier: Modifier) {
@Composable @Composable
private fun CameraPreviewWithOverlay( private fun CameraPreviewWithOverlay(
onImageAnalyzed: (ImageProxy) -> Unit, cameraPreview: @Composable () -> Unit,
captureController: CameraCaptureController,
liveAnalysisState: LiveAnalysisState liveAnalysisState: LiveAnalysisState
) { ) {
val width = LocalConfiguration.current.screenWidthDp val width = LocalConfiguration.current.screenWidthDp
@@ -210,10 +235,7 @@ private fun CameraPreviewWithOverlay(
.width(width.dp) .width(width.dp)
.height(height.dp) .height(height.dp)
) { ) {
CameraPreview( cameraPreview()
onImageAnalyzed = onImageAnalyzed,
captureController = captureController
)
AnalysisOverlay(liveAnalysisState) AnalysisOverlay(liveAnalysisState)
} }
} }
@@ -405,3 +427,26 @@ fun CameraScreenFooter(
} }
} }
} }
@androidx.compose.ui.tooling.preview.Preview(showBackground = true)
@Composable
fun CameraScreenPreview() {
MyScanTheme {
CameraScreenContent(
modifier = Modifier,
cameraPreview = {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.DarkGray),
contentAlignment = Alignment.Center
) {
Text("Camera Preview", color = Color.White)
}
},
pageCount = 3,
liveAnalysisState = LiveAnalysisState(),
onCapture = {},
onFinalizePressed = {})
}
}