如何在Android Canvas上绘制带圆角的六边形?
绘制带圆角的六边形
我想要绘制一个带圆角的六边形,但毫无头绪。我尝试过cubicTo、arcTo等多种方法。

以下是我当前的绘制代码:
fun Path.customHexagon(radius: Float, size: Size) { val triangleHeight = (sqrt(3.0) * radius / 2) val centerX = size.width / 2 val centerY = size.height / 2 moveTo(centerX, centerY + radius) lineTo((centerX - triangleHeight).toFloat(), centerY + radius/2) lineTo((centerX - triangleHeight).toFloat(), centerY - radius/2) lineTo(centerX, centerY - radius) lineTo((centerX + triangleHeight).toFloat(), centerY - radius/2) lineTo((centerX + triangleHeight).toFloat(), centerY + radius/2) close() }
解决方案
要实现带圆角的六边形,核心是用arcTo替换每个顶点的直角连接,让每个角平滑过渡。下面是修改后的代码:
import android.graphics.PointF import kotlin.math.cos import kotlin.math.sin import kotlin.math.sqrt import kotlin.math.toRadians fun Path.customRoundedHexagon(radius: Float, size: Size, cornerRadius: Float) { val triangleHeight = (sqrt(3.0) * radius / 2).toFloat() val centerX = size.width / 2 val centerY = size.height / 2 // 六边形的六个顶点坐标 val vertices = listOf( PointF(centerX, centerY + radius), PointF(centerX - triangleHeight, centerY + radius/2), PointF(centerX - triangleHeight, centerY - radius/2), PointF(centerX, centerY - radius), PointF(centerX + triangleHeight, centerY - radius/2), PointF(centerX + triangleHeight, centerY + radius/2) ) // 每个顶点对应的方向角度(用于计算切线) val vertexAngles = listOf(270f, 210f, 150f, 90f, 30f, 330f) val arcAngle = 60f // 六边形内角120°,圆弧覆盖60°实现圆角 // 移动到第一个边的起始点(避开圆角区域) val startAngle = vertexAngles[0] + 30f moveTo( vertices[0].x + cornerRadius * cos(startAngle.toRadians()), vertices[0].y + cornerRadius * sin(startAngle.toRadians()) ) // 遍历每个顶点,绘制圆角圆弧 for (i in vertices.indices) { val nextIndex = (i + 1) % vertices.size val currentVertex = vertices[i] val nextVertex = vertices[nextIndex] // 计算圆弧的边界矩形和角度参数 val left = currentVertex.x - cornerRadius * cos((vertexAngles[i] - 30f).toRadians()) val top = currentVertex.y - cornerRadius * sin((vertexAngles[i] - 30f).toRadians()) val right = currentVertex.x + cornerRadius * cos((vertexAngles[nextIndex] + 30f).toRadians()) val bottom = currentVertex.y + cornerRadius * sin((vertexAngles[nextIndex] + 30f).toRadians()) arcTo( left, top, right, bottom, vertexAngles[i] - 60f, arcAngle, false ) } close() } // 扩展函数:角度转弧度 private fun Float.toRadians() = this.toDouble().toRadians().toFloat()
关键说明
cornerRadius参数用于控制圆角大小,建议取值不超过triangleHeight * 0.5,避免图形变形- 利用六边形每个内角120°的特性,通过
arcTo绘制60°的圆弧来实现圆角,保证边与圆弧平滑连接 - 所有顶点坐标计算逻辑和原代码保持一致,只修改了顶点处的连接方式
内容的提问来源于stack exchange,提问作者xMaster
相关产品推荐
相关产品推荐

