Jetpack 中的形状组成 android

问题描述 投票:0回答:1

我正在尝试在 Jetpack Compose 中创建具有特定形状的自定义卡片。我希望卡片类似于具有圆角和自定义轮廓的特定形状(如下图所示)。

我已经从下面的代码开始,但我不确定如何调整曲线和形状以完全匹配图像。这是目标卡片形状图像:

Custom Card

如何制作与图片类似的背景?

这是我的代码,我已经尝试过但无法实现类似的形状。

@Composable
fun CustomCard(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    val radius = with(LocalDensity.current) { 19.dp.toPx() }
    val cornerRadiusDp = 80.dp
    val cornerRadius = with(LocalDensity.current) { cornerRadiusDp.toPx() }

    val padding = 10.dp

    // Create a custom shape
    val shape = remember {
        GenericShape { size, _ ->
            val width = size.width
            val height = size.height

            moveTo(0f, radius)
            quadraticTo(0f, 0f, radius, 0f)
            lineTo(width - cornerRadius - radius, 0f)
            quadraticTo(width - cornerRadius, 0f, width - cornerRadius, radius)

            quadraticTo(width - 1.1f*cornerRadius, 1.1f*cornerRadius, width - radius, cornerRadius)

            quadraticTo(width, cornerRadius, width, cornerRadius + radius)

            lineTo(width, height - radius)
            quadraticTo(width, height, width - radius, height)

            lineTo(radius, height)
            quadraticTo(0f, height, 0f, height - radius)

            lineTo(0f, radius)
        }
    }

    Box(modifier = modifier) {
        Card(
            modifier = Modifier.fillMaxSize(),
            shape = shape,
            colors = CardDefaults.cardColors(
                containerColor = Color(0xFFBFE8FB)
            )
        ) {
            content()
        }

        Box(
            modifier = Modifier
                .size(cornerRadiusDp - padding)
                .align(Alignment.TopEnd)
                .background(
                    color = Color.Blue,
                    shape = CircleShape
                )
        ){
            Text(
                text = "1",
                color = Color.White,
                modifier = Modifier.align(Alignment.Center)
            )
        }
    }
}

@Preview
@Composable
fun ContextCardPreview() {
    Column(modifier = Modifier.background(Color.Red)){
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            CustomCard(modifier = Modifier
                .width(200.dp)
                .height(180.dp)
            ) {

                val price = buildAnnotatedString {
                    withStyle(SpanStyle(color = Color.Green)) { append("$") }
                    append("0.00")
                }

                val labelStyle = remember {
                    TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Light)
                }

                val priceStyle = remember {
                    TextStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)
                }

                Column(
                    modifier = Modifier.padding(10.dp)
                ) {
                    Text(text = "Text", fontSize = 18.sp)
                    //Text(text = price, style = priceStyle)

                    Spacer(modifier = Modifier.weight(0.8f))

                    Text(text = "Text", style = labelStyle)

                    Spacer(modifier = Modifier.weight(0.5f))
                    Text(text = price, style = priceStyle)
                    Spacer(modifier = Modifier.weight(0.04f))
                }
            }
        }

    }
}
android kotlin android-jetpack-compose android-jetpack-compose-material3
1个回答
0
投票

我已参考this帖子并进行了一些更改以实现您所需要的。

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.GenericShape
import androidx.compose.material3.Card
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp

@Composable
fun CardExample(){
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        CustomCard(modifier = Modifier
            .width(200.dp)
            .height(200.dp)
        ) {

        }
    }

}

@Preview
@Composable
fun CardPreview(){
    CardExample()
}

@Composable
fun CustomCard(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    val radius = with(LocalDensity.current) { 30.dp.toPx() }

    val cornerRadiusDp = 80.dp
    val cornerRadius = with(LocalDensity.current) { cornerRadiusDp.toPx() }

    val padding = 15.dp

    // Create a custom shape
    val shape = remember {
        GenericShape { size, _ ->
            val width = size.width
            val height = size.height

            moveTo(0f, radius)
            quadraticBezierTo(0f, 0f, radius, 0f)
            lineTo(width - cornerRadius - radius, 0f)
            quadraticBezierTo(width - cornerRadius, 10f, width - cornerRadius, radius)

            quadraticBezierTo(width - 1.0f*cornerRadius, 1.0f*cornerRadius, width - radius, cornerRadius)

            quadraticBezierTo(width, cornerRadius, width, cornerRadius + radius)

            lineTo(width, height - radius)
            quadraticBezierTo(width, height, width - radius, height)

            lineTo(radius, height)
            quadraticBezierTo(0f, height, 0f, height - radius)

            lineTo(0f, radius)
        }
    }

    Box(modifier = modifier) {
        Card(
            modifier = Modifier.fillMaxSize(),
            shape = shape
        ) {
            content()
        }

        Box(
            modifier = Modifier
                .size(cornerRadiusDp - padding)
                .align(Alignment.TopEnd)
                .background(
                    color = Color.White,
                    shape = CircleShape
                )
        ){
            Image(
                painter = painterResource(id = R.drawable.etherium),
                contentDescription = "",
                contentScale = ContentScale.Fit,
                modifier = Modifier.fillMaxWidth()
            )
        }
    }
}

output

© www.soinside.com 2019 - 2024. All rights reserved.