2017-09-20 154 views
0

我創建了一個具有路徑的自定義矩形形狀,您可以在其中控制如何繪製所有邊角:不是圓形,圓形「內部」(它是普通的圓角),圓形「外部」(請參見圖片)。代碼:Android路徑形狀未正確填充

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但他們沒有適當的填充矩形。 我的代碼有什麼問題?

+0

而不close()剛剛從當前點添加段第一點,是不是? –

+0

好吧,對於內部你總是90度然後外面不應該總是-90度? – pskink

+0

@pskink,謝謝,你完全正確,當我繪製「外部」弧線段時,它從末端線段點開始到開始線段點,這會導致路徑分裂。 –

回答

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