В настоящее время я решаю две проблемы. Высота красного поля кажется правильной, но ширина слишком мала, и я не знаю почему. Вторая проблема заключается в том, что когда я перемещаю свой телефон, ограничивающая рамка перемещается повсюду и не привязана к реальному QR-коду. Я не знаю, как это исправить.

Вот моя компонуемая функция CameraView...
@Composable
fun CameraPreview() {
val context = LocalContext.current
val scanner = MultiFormatReader().apply {
val hints: MutableMap = EnumMap(DecodeHintType::class.java)
hints[DecodeHintType.POSSIBLE_FORMATS] = listOf(BarcodeFormat.QR_CODE)
setHints(hints)
}
val qrCodeBounds = remember { mutableStateOf(null) }
BoxWithConstraints(modifier = Modifier.fillMaxSize()) {
val screenWidth = maxWidth
val scanBoxSize = screenWidth * 0.6f // adjust the size of the scanning area here
AndroidView(
factory = { ctx ->
val previewView = PreviewView(ctx)
val cameraProviderFuture = ProcessCameraProvider.getInstance(ctx)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val imageAnalysis = ImageAnalysis.Builder()
.build()
.also {
it.setAnalyzer(ContextCompat.getMainExecutor(ctx)) { imageProxy ->
val result = scanQRCode(imageProxy, scanner)
imageProxy.close()
if (result != null) {
println("QR Code found: ${result.text}")
println("Image Proxy Width: ${imageProxy.width}, Height: ${imageProxy.height}")
qrCodeBounds.value = getBoundingBox(result.resultPoints, imageProxy.width, imageProxy.height, previewView.width, previewView.height)
} else {
qrCodeBounds.value = null
}
}
}
try {
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
context as ComponentActivity,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageAnalysis
)
} catch (exc: Exception) {
// Handle exceptions
}
}, ContextCompat.getMainExecutor(ctx))
previewView
},
modifier = Modifier.fillMaxSize()
)
Box(modifier = Modifier
.matchParentSize()
.background(Color.Black.copy(alpha = 0.8f))
)
// Scanning area box with a clear cutout
Box(
modifier = Modifier
.size(scanBoxSize)
.align(Alignment.Center)
.drawBehind {
// Draw a rounded clear rectangle to create a cutout effect
drawRoundRect(
color = Color.Transparent,
topLeft = Offset(0f, 0f),
size = Size(size.width, size.height),
cornerRadius = CornerRadius(x = 12.dp.toPx(), y = 12.dp.toPx()),
blendMode = BlendMode.Clear
)
}
.border(2.dp, MaterialTheme.colorScheme.onPrimary, RoundedCornerShape(12.dp))
)
qrCodeBounds.value?.let { bounds ->
Canvas(modifier = Modifier.fillMaxSize()) {
drawRect(
color = Color.Red,
topLeft = Offset(bounds.left.toFloat(), bounds.top.toFloat()),
size = Size(bounds.width().toFloat(), bounds.height().toFloat()),
style = Stroke(width = 3.dp.toPx())
)
}
}
}
}
Это моя функция getBoundingBox
private fun getBoundingBox(resultPoints: Array?, imageWidth: Int, imageHeight: Int, previewWidth: Int, previewHeight: Int): Rect? {
if (resultPoints == null || resultPoints.size != 4) {
return null
}
// Calculate scale factors
val scaleX = previewWidth.toFloat() / imageWidth
val scaleY = previewHeight.toFloat() / imageHeight
// Apply scale factors to the coordinates
val left = (resultPoints[0].x * scaleX).toInt()
val top = (resultPoints[0].y * scaleY).toInt()
val right = (resultPoints[2].x * scaleX).toInt()
val bottom = (resultPoints[2].y * scaleY).toInt()
return Rect(left, top, right, bottom)
}
А это моя функция scanQRCode
private fun scanQRCode(imageProxy: ImageProxy, scanner: MultiFormatReader): Result? {
val data = imageProxy.planes[0].buffer.let { buffer ->
val data = ByteArray(buffer.capacity())
buffer.get(data)
buffer.clear()
data
}
val source = PlanarYUVLuminanceSource(
data,
imageProxy.width,
imageProxy.height,
0,
0,
imageProxy.width,
imageProxy.height,
false
)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
return try {
scanner.decodeWithState(binaryBitmap)
} catch (e: Exception) {
null // QR Code not found
}
}
Подробнее здесь: https://stackoverflow.com/questions/778 ... nd-qr-code
Мобильная версия