Reputation: 455
I'm creating a QR Scanner where the preview view is blur except the centre square part, I was able to blur PreviewView but not able to think of a way to unblur the centre cutout part.
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
val previewView = PreviewView(context).apply {
setRenderEffect( RenderEffect.createBlurEffect(
26f, 26f,Shader.TileMode.CLAMP))
implementationMode = PreviewView.ImplementationMode.COMPATIBLE
}
val preview = Preview.Builder().build()
val selector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
preview.setSurfaceProvider(previewView.surfaceProvider)
val imageAnalysis = ImageAnalysis.Builder().setTargetResolution(
Size(
previewView.width, previewView.height
)
).setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build()
imageAnalysis.setAnalyzer(
ContextCompat.getMainExecutor(context),
QrCodeAnalyzer { result ->
onScan(result)
})
try {
camera = cameraProviderFuture.get().bindToLifecycle(
lifecycleOwner, selector, preview, imageAnalysis, imageCapture
)
} catch (e: Exception) {
e.printStackTrace()
}
previewView
},
)
if (overlay != null) {
overlay()
}
Upvotes: 4
Views: 853
Reputation: 93
Parent component:
Box(contentAlignment = Alignment.Center) {
CameraView()
ScannerArea(modifier = Modifier.fillMaxSize())
//some buttons (flash, take photo)
....
}
ScannerArea:
@Composable
fun ScannerArea(
modifier: Modifier,
horizontalPadding: Dp = 36.dp,
scannerHeight: Dp = 280.dp,
scannerCornerRadius: Dp = 8.dp,
scannerStrokeWidth: Dp = 2.dp,
scannerColor: Color = Color(0xFFFFFFFFF),
darkTint: Color = Color(0x40000000)
) {
Canvas(modifier = modifier) {
val horizontalPaddingPx = horizontalPadding.toPx()
val scannerHeightPx = scannerHeight.toPx()
val scannerCornerRadiusPx = scannerCornerRadius.toPx()
val scannerStrokeWidthPx = scannerStrokeWidth.toPx()
val scannerPath = getScannerPath(
size = size,
scannerHeight = scannerHeightPx,
horizontalPadding = horizontalPaddingPx,
scannerCornerRadius = scannerCornerRadiusPx
)
clipPath(path = scannerPath, clipOp = ClipOp.Difference) {
drawRect(color = darkTint, size = size)
}
drawPath(
path = scannerPath,
color = scannerColor,
style = Stroke(width = scannerStrokeWidthPx)
)
}
}
private fun getScannerPath(
size: Size,
scannerHeight: Float,
horizontalPadding: Float,
scannerCornerRadius: Float
) = Path().apply {
moveTo(
x = horizontalPadding + scannerCornerRadius,
y = size.center.y - scannerHeight / 2f
)
lineTo(
x = size.width - horizontalPadding - scannerCornerRadius,
y = size.center.y - scannerHeight / 2f
)
quadraticBezierTo(
x1 = size.width - horizontalPadding,
y1 = size.center.y - scannerHeight / 2f,
x2 = size.width - horizontalPadding,
y2 = size.center.y - scannerHeight / 2f + scannerCornerRadius
)
lineTo(
x = size.width - horizontalPadding,
y = size.center.y + scannerHeight / 2f - scannerCornerRadius
)
quadraticBezierTo(
x1 = size.width - horizontalPadding,
y1 = size.center.y + scannerHeight / 2f,
x2 = size.width - scannerCornerRadius - horizontalPadding,
y2 = size.center.y + scannerHeight / 2f
)
lineTo(
x = horizontalPadding + scannerCornerRadius,
y = size.center.y + scannerHeight / 2f
)
quadraticBezierTo(
x1 = horizontalPadding,
y1 = size.center.y + scannerHeight / 2f,
x2 = horizontalPadding,
y2 = size.center.y + scannerHeight / 2f - scannerCornerRadius
)
lineTo(
x = horizontalPadding,
y = size.center.y - scannerHeight / 2f + scannerCornerRadius
)
quadraticBezierTo(
x1 = horizontalPadding,
y1 = size.center.y - scannerHeight / 2f,
x2 = horizontalPadding + scannerCornerRadius,
y2 = size.center.y - scannerHeight / 2f
)
}
Upvotes: 1