Android Path形状未正确填充

时间:2017-09-20 11:11:30

标签: android canvas path drawable

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

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)
    }

stroke, all corners outside 但是当我用填充类型绘制时,它填充如下图所示: enter image description here 我已经尝试了所有Path.FillTypes,但它们都没有正确填充矩形。 我的代码出了什么问题?

1 个答案:

答案 0 :(得分:0)

@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)
        }
    }
}

final result