【问题标题】:Android Path shape not filled properlyAndroid路径形状未正确填充
【发布时间】:2018-03-01 10:10:29
【问题描述】:

我创建了一个带有路径的自定义矩形形状,您可以在其中控制如何绘制所有角:不是圆形的,圆形的“内部”(它是普通的圆角),圆形的“外部”(见图)。代码:

enum class CornerType {
    NOT_ROUNDED,
    ROUNDED_INSIDE,
    ROUNDED_OUTSIDE
}

object CustomShapes {

    fun rectangleWithRoundedCorners(path: Path, rect: Rect, cornerRadius: Int,
                                    topLeft: CornerType, topRight: CornerType,
                                    bottomLeft: CornerType, bottomRight: CornerType){

        val topLeftX = when(topLeft){
            CornerType.NOT_ROUNDED -> rect.left
            CornerType.ROUNDED_INSIDE -> rect.left + cornerRadius
            CornerType.ROUNDED_OUTSIDE -> rect.left - cornerRadius
        }.toFloat()
        val topLeftY = rect.top.toFloat()

        val topRightX = when(topRight){
            CornerType.NOT_ROUNDED -> rect.right
            CornerType.ROUNDED_INSIDE -> rect.right - cornerRadius
            CornerType.ROUNDED_OUTSIDE -> rect.right + cornerRadius
        }.toFloat()
        val topRightY = rect.top.toFloat()

        val bottomLeftX = when(bottomLeft){
            CornerType.NOT_ROUNDED -> rect.left
            CornerType.ROUNDED_INSIDE -> rect.left + cornerRadius
            CornerType.ROUNDED_OUTSIDE -> rect.left - cornerRadius
        }.toFloat()
        val bottomLeftY = rect.bottom.toFloat()

        val bottomRightX = when(bottomRight){
            CornerType.NOT_ROUNDED -> rect.right
            CornerType.ROUNDED_INSIDE -> rect.right - cornerRadius
            CornerType.ROUNDED_OUTSIDE -> rect.right + cornerRadius
        }.toFloat()
        val bottomRightY = rect.bottom.toFloat()


        path.reset()
        //1
        path.moveTo(topLeftX, topLeftY)
        //2
        path.lineTo(topRightX, topRightY)

        //3
        when(topRight){
            CornerType.NOT_ROUNDED -> path.lineTo(topRightX, topRightY + cornerRadius.toFloat())
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(topRightX - cornerRadius, topRightY,
                        topRightX + cornerRadius, topRightY + 2*cornerRadius), 270f, 90f, true)
                path.moveTo(topRightX + cornerRadius, topRightY + cornerRadius)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(topRightX - cornerRadius, topRightY,
                        topRightX + cornerRadius, topRightY + 2*cornerRadius), 180f, 90f, true)
                path.moveTo(topRightX - cornerRadius, topRightY + cornerRadius)
            }
        }
        //4
        path.lineTo(rect.right.toFloat(), bottomRightY - cornerRadius)
        //5
        when(bottomRight){
            CornerType.NOT_ROUNDED -> path.lineTo(bottomRightX, bottomRightY)
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(bottomRightX - cornerRadius, bottomRightY - 2*cornerRadius,
                        bottomRightX + cornerRadius, bottomRightY), 0f, 90f, true)
                path.moveTo(bottomRightX, bottomRightY)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(bottomRightX - cornerRadius, bottomRightY - 2*cornerRadius,
                        bottomRightX + cornerRadius, bottomRightY), 90f, 90f, true)
                path.moveTo(bottomRightX, bottomRightY)
            }
        }
        //6
        path.lineTo(bottomLeftX, bottomLeftY)
        //7
        when(bottomLeft){
            CornerType.NOT_ROUNDED -> path.lineTo(bottomLeftX, bottomRightY - cornerRadius)
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(bottomLeftX - cornerRadius, bottomLeftY - 2 * cornerRadius,
                        bottomLeftX + cornerRadius, bottomLeftY), 90f, 90f, true)
                path.moveTo(bottomLeftX - cornerRadius, bottomLeftY - cornerRadius)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(bottomLeftX - cornerRadius, bottomLeftY - 2*cornerRadius,
                        bottomLeftX + cornerRadius, bottomLeftY), 0f, 90f, true)
                path.moveTo(bottomLeftX + cornerRadius, bottomLeftY - cornerRadius)
            }
        }
        //8
        path.lineTo(rect.left.toFloat(), topLeftY + cornerRadius)
        //9
        when(topLeft){
            CornerType.NOT_ROUNDED -> path.lineTo(topLeftX, topLeftY)
            CornerType.ROUNDED_INSIDE -> path.arcTo(RectF(topLeftX - cornerRadius, topLeftY,
                        topLeftX + cornerRadius, topLeftY + 2*cornerRadius), 180f, 90f, true)
            CornerType.ROUNDED_OUTSIDE -> path.arcTo(RectF(topLeftX - cornerRadius, topLeftY,
                        topLeftX + cornerRadius, topLeftY + 2*cornerRadius), 270f, 90f, true)
        }
    }
}

当我尝试用笔画来绘制它时,似乎一切都如我所料。

override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val paint = Paint()
        paint.color = Color.RED
        //paint.strokeWidth = 3f
        paint.style = Paint.Style.STROKE
        paint.isAntiAlias = true

        val path = Path()

        path.fillType = Path.FillType.EVEN_ODD
        CustomShapes.rectangleWithRoundedCorners(path, Rect(100, 100, 600, 600), 50, CornerType.ROUNDED_OUTSIDE, CornerType.ROUNDED_OUTSIDE, CornerType.ROUNDED_OUTSIDE, CornerType.ROUNDED_OUTSIDE)
        canvas.drawPath(path, paint)
    }

但是当我使用填充类型绘制时,它会填充如下图: 我已经尝试了所有 Path.FillTypes 但它们都没有正确填充矩形。 我的代码有什么问题?

【问题讨论】:

  • 但是 close() 只是从当前点添加段到第一个点,不是吗?
  • 在里面你总是有 90 度,那么对于外面不应该总是 -90 度吗?
  • @pskink,谢谢,你绝对正确,当我绘制“外部”弧段时,它是从结束段点绘制到开始段点,这会导致路径中断。
  • 当然你也需要改变起始角度...

标签: android canvas path drawable


【解决方案1】:

@pskink 正确地指出问题是因为“外部”弧线的绘制方向错误。 更正的绘图代码:

        path.reset()
        //1
        path.moveTo(topLeftX, topLeftY)
        //2
        path.lineTo(topRightX, topRightY)

        //3
        when(topRight){
            CornerType.NOT_ROUNDED -> path.lineTo(topRightX, topRightY + cornerRadius.toFloat())
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(topRightX - cornerRadius, topRightY,
                        topRightX + cornerRadius, topRightY + 2*cornerRadius), 270f, 90f, false)
                //path.moveTo(topRightX + cornerRadius, topRightY + cornerRadius)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(topRightX - cornerRadius, topRightY,
                        topRightX + cornerRadius, topRightY + 2*cornerRadius), 270f, -90f, false)
                //path.moveTo(topRightX - cornerRadius, topRightY + cornerRadius)
            }
        }
        //4
        path.lineTo(rect.right.toFloat(), bottomRightY - cornerRadius)
        //5
        when(bottomRight){
            CornerType.NOT_ROUNDED -> path.lineTo(bottomRightX, bottomRightY)
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(bottomRightX - cornerRadius, bottomRightY - 2*cornerRadius,
                        bottomRightX + cornerRadius, bottomRightY), 0f, 90f, false)
                //path.moveTo(bottomRightX, bottomRightY)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(bottomRightX - cornerRadius, bottomRightY - 2*cornerRadius,
                        bottomRightX + cornerRadius, bottomRightY), 180f, -90f, false)
                //path.moveTo(bottomRightX, bottomRightY)
            }
        }
        //6
        path.lineTo(bottomLeftX, bottomLeftY)
        //7
        when(bottomLeft){
            CornerType.NOT_ROUNDED -> path.lineTo(bottomLeftX, bottomRightY - cornerRadius)
            CornerType.ROUNDED_INSIDE -> {
                path.arcTo(RectF(bottomLeftX - cornerRadius, bottomLeftY - 2 * cornerRadius,
                        bottomLeftX + cornerRadius, bottomLeftY), 90f, 90f, false)
                //path.moveTo(bottomLeftX - cornerRadius, bottomLeftY - cornerRadius)
            }
            CornerType.ROUNDED_OUTSIDE -> {
                path.arcTo(RectF(bottomLeftX - cornerRadius, bottomLeftY - 2*cornerRadius,
                        bottomLeftX + cornerRadius, bottomLeftY), 90f, -90f, false)
                //path.moveTo(bottomLeftX + cornerRadius, bottomLeftY - cornerRadius)
            }
        }
        //8
        path.lineTo(rect.left.toFloat(), topLeftY + cornerRadius)
        //9
        when(topLeft){
            CornerType.NOT_ROUNDED -> path.lineTo(topLeftX, topLeftY)
            CornerType.ROUNDED_INSIDE -> path.arcTo(RectF(topLeftX - cornerRadius, topLeftY,
                        topLeftX + cornerRadius, topLeftY + 2*cornerRadius), 180f, 90f, false)
            CornerType.ROUNDED_OUTSIDE -> path.arcTo(RectF(topLeftX - cornerRadius, topLeftY,
                        topLeftX + cornerRadius, topLeftY + 2*cornerRadius), 0f, -90f, false)
        }
    }
}

【讨论】:

    猜你喜欢
    • 2019-07-06
    • 1970-01-01
    • 2017-03-12
    • 1970-01-01
    • 2016-05-24
    • 2023-03-22
    • 2016-04-16
    • 1970-01-01
    • 2020-11-29
    相关资源
    最近更新 更多