我曾try 在Jetpack Compose中创建一个六边形形状,但只能达到尖端,try 了几种方法,使用Square BezierTo和圆弧,但无法实现弯曲端的效果.

我试着在网上看看,但不完全是我想要的,如果你知道如何实现它,谢谢你回复这个帖子.

以下是当前代码中没有弧形结尾的代码:

class HexagonShape : Shape {

    override fun createOutline(
        size: Size,
        layoutDirection: LayoutDirection,
        density: Density
    ): Outline {
        return Outline.Generic(
            path = drawCustomHexagonPath(size)
        )
    }
}

private fun drawCustomHexagonPath(size: Size): Path {
    return Path().apply {
        val radius = min(size.width / 2f, size.height / 2f)
        val triangleHeight = (sqrt(3.0) * radius / 2)
        val centerX = size.width / 2
        val centerY = size.height / 2

        moveTo(x = centerX, y = centerY + radius)

        lineTo(x = (centerX - triangleHeight).toFloat(), y = centerY + radius / 2)
        lineTo(x = (centerX - triangleHeight).toFloat(), y = centerY - radius / 2)
        lineTo(x = centerX, y = centerY - radius)
        lineTo(x = (centerX + triangleHeight).toFloat(), y = centerY - radius / 2)
        lineTo(x = (centerX + triangleHeight).toFloat(), y = centerY + radius / 2)

        close()
    }
}

@Composable
fun Hexagon(modifier: Modifier = Modifier) {
    Box(
        modifier = modifier
            .clip(HexagonShape())
            .background(md_theme_light_inversePrimary)
            .width(500.dp)
            .height(500.dp),
        contentAlignment = Alignment.Center
    ) {
        Image(
            painter = painterResource(id = R.drawable.app_bg),
            contentDescription = "My Hexagon Image",
            contentScale = ContentScale.Crop,
            modifier = Modifier
                .wrapContentSize()
                .background(color = Color.Cyan)
        )
    }
}

推荐答案

你可以用pathEffect = PathEffect.cornerPathEffect(cornerRadius)

enter image description here

@Composable
private fun DrawPolygonPath() {
    var sides by remember { mutableStateOf(3f) }
    var cornerRadius by remember { mutableStateOf(1f) }

    Canvas(modifier = canvasModifier) {
        val canvasWidth = size.width
        val canvasHeight = size.height
        val cx = canvasWidth / 2
        val cy = canvasHeight / 2
        val radius = (canvasHeight - 20.dp.toPx()) / 2
        val path = createPolygonPath(cx, cy, sides.roundToInt(), radius)

        drawPath(
            color = Color.Red,
            path = path,
            style = Stroke(
                width = 4.dp.toPx(),
                pathEffect = PathEffect.cornerPathEffect(cornerRadius)
            )
        )
    }

    Column(modifier = Modifier.padding(horizontal = 20.dp)) {
        Text(text = "Sides ${sides.roundToInt()}")
        Slider(
            value = sides,
            onValueChange = { sides = it },
            valueRange = 3f..12f,
            steps = 10
        )

        Text(text = "CornerRadius ${cornerRadius.roundToInt()}")

        Slider(
            value = cornerRadius,
            onValueChange = { cornerRadius = it },
            valueRange = 0f..50f,
        )
    }
}

和多边形函数

fun createPolygonPath(cx: Float, cy: Float, sides: Int, radius: Float): Path {
    val angle = 2.0 * Math.PI / sides

    return Path().apply {
        moveTo(
            cx + (radius * cos(0.0)).toFloat(),
            cy + (radius * sin(0.0)).toFloat()
        )
        for (i in 1 until sides) {
            lineTo(
                cx + (radius * cos(angle * i)).toFloat(),
                cy + (radius * sin(angle * i)).toFloat()
            )
        }
        close()
    }
}

你可以从线圈中得到ImageBitmap,然后你可以像这样用BlendMode来画它

enter image description here

@Preview
@Composable
fun ImageTest() {
    Column(
        modifier = Modifier.fillMaxSize().padding(32.dp)
    ) {
        val imageBitmap = ImageBitmap.imageResource(R.drawable.avatar_1_raster)

        Box(
            Modifier
                .size(200.dp)
                .border(2.dp, Color.Green)
                .graphicsLayer {
                    compositingStrategy = CompositingStrategy.Offscreen
                }
                .drawWithCache {
                    val canvasWidth = size.width
                    val canvasHeight = size.height
                    val cx = canvasWidth / 2
                    val cy = canvasHeight / 2
                    val radius = canvasHeight / 4
                    val path = createPolygonPath(cx, cy, 6, radius)

                    onDrawWithContent {

                        // Source
                        drawPath(
                            path = path,
                            color = Color.Red,
                            style = Stroke(
                                width = canvasHeight / 2,
                                pathEffect = PathEffect.cornerPathEffect(15f)
                            )
                        )

                        drawCircle(
                            color = Color.Red,
                            radius = 10f
                        )

                        // Destination
                        drawImage(
                            image = imageBitmap,
                            dstSize = IntSize(size.width.toInt(), size.height.toInt()),
                            blendMode = BlendMode.SrcIn
                        )
                    }
                }
        )
    }
}

Android相关问答推荐

替换- prop -中的值(adb shell getprop)

如何从Android 12的来电中获取电话号码?

不能在LazyGrid-Jetpack Compose中使用填充最大宽度或填充父项最大宽度

在以XML格式设置完整屏幕视图时可见App Compat按钮

从惰性列中删除项目时Jetpack Compose崩溃

如何在Jetpack Compose中将对象的移动从一个路径平滑地切换到另一个路径?

页面更改时不显示 cogo toast 消息

弹出导航堆栈后,Compose 无法访问 Hilt View Model

从我的 Android 应用程序发送到 Gin 时失败,但从 Postman 发送到 Gin 时成功

retrofit2.HttpException: HTTP 401

将 React Native 应用程序背景带到前台

如何使用滑行加载媒体的专辑封面?

在 jetpack compose 中交替使用 View.INVISIBLE

从 Firebase 云存储中获取照片会导致 Android Jetpack Compose 闪烁

如何在屏幕旋转或系统主题更改后将光标移动到 TextField 的末尾并保持键盘显示?

无法 HEAD 'https://jcenter.bintray.com/com/facebook/react/react-native/maven-metadata.xml'

有什么方法可以确定正在使用哪个 Android 手机的麦克风进行录音?

新的内部测试应用程序版本不适用于测试人员,即使它说它们是

在jetpack compose中看不到圆角

compose FontFamily 错误:必须初始化变量