如何在 jetpack compose 中实现以下布局?

Kun*_*war 3 android android-layout kotlin android-jetpack android-jetpack-compose

这个布局是我做的,你正在看的布局是一个 SVG 图像,所以我刚刚制作了图像以填充最大尺寸,并在下面添加了上面的文本和相机捕获按钮。但现在我想删除图像背景并希望以编程方式制作相同的布局。

在此输入图像描述

Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.fillMaxSize()) {
    AndroidView({ previewView }, modifier = Modifier.fillMaxSize())

    Column(modifier = Modifier.fillMaxSize()) {

        Icon(
            painter = painterResource(id = R.drawable.ic_card_overlay),
            contentDescription = null
        )

        Image(
            modifier = Modifier.fillMaxSize(),
            painter = painterResource(id = R.drawable.ic_black_transparent),
            contentDescription = null,
            contentScale = ContentScale.FillWidth
        )
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(26.dp)
    ) {

        Row(
            modifier = Modifier
                .padding(bottom = 20.dp), verticalAlignment = Alignment.CenterVertically
        ) {

            Icon(
                modifier = Modifier.clickable {
                    onCloseCameraClick()
                },
                painter = painterResource(id = R.drawable.ic_baseline_arrow_back_ios_24),
                contentDescription = null,
                tint = Color.White
            )

            Text(
                text = "Passport",
                color = Color.White,
                fontSize = 20.sp
            )
        }

        Text(
            text = "Place your passport inside the frame and take a\npicture.\nMake sure it is not cut or has any glare.",
            color = Color.White,
            fontSize = 12.sp
        )
    }

    IconButton(
        modifier = Modifier.padding(bottom = 20.dp),
        onClick = {
            Log.d("takePhoto", "ON CLICK")
            takePhoto(
                imageCapture = imageCapture,
                outputDirectory = outputDirectory,
                executor = executor,
                onImageCaptured = onImageCaptured,
                onError = onError
            )
        },
        content = {
            Icon(
                painter = painterResource(id = R.drawable.ic_baseline_camera_24),
                contentDescription = stringResource(R.string.take_picture),
                tint = Color.White,
                modifier = Modifier
                    .fillMaxSize(0.2f)
            )
        }
    )
}
Run Code Online (Sandbox Code Playgroud)

你可以看到我使用了 ic_card_overlay 图像,它就像背景一样。我想实现与中间的框相同的黑色透明背景,其中不包括黑色透明颜色。谢谢。

Thr*_*ian 7

您可以使用 BlendMode.Clear 来实现此目的

@Composable
fun TransparentClipLayout(
    modifier: Modifier,
    width: Dp,
    height: Dp,
    offsetY: Dp
) {

    val offsetInPx: Float
    val widthInPx: Float
    val heightInPx: Float

    with(LocalDensity.current) {
        offsetInPx = offsetY.toPx()
        widthInPx = width.toPx()
        heightInPx = height.toPx()
    }

    Canvas(modifier = modifier) {

        val canvasWidth = size.width

        with(drawContext.canvas.nativeCanvas) {
            val checkPoint = saveLayer(null, null)

            // Destination
            drawRect(Color(0x77000000))

            // Source
            drawRoundRect(
                topLeft = Offset(
                    x = (canvasWidth - widthInPx) / 2,
                    y = offsetInPx
                ),
                size = Size(widthInPx, heightInPx),
                cornerRadius = CornerRadius(30f,30f),
                color = Color.Transparent,
                blendMode = BlendMode.Clear
            )
            restoreToCount(checkPoint)
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

您也可以自定义圆角半径大小。这仅用于演示

用法

Column {

    Box(modifier = Modifier.fillMaxSize()) {
        Image(
            modifier =Modifier.fillMaxSize(),
            painter = painterResource(id = R.drawable.landscape1),
            contentDescription = null,
            contentScale = ContentScale.Crop
        )
        TransparentClipLayout(
            modifier = Modifier.fillMaxSize(),
            width = 300.dp,
            height = 200.dp,
            offsetY = 150.dp
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述