How to use android canvas to draw a Rectangle with only topleft and topright corners round?

前端 未结 15 2068
后悔当初
后悔当初 2020-11-29 01:58

I found a function for rectangles with all 4 corners being round, but I want to have just the top 2 corners round. What can I do?

canvas.drawRoundRect(new Re         


        
相关标签:
15条回答
  • 2020-11-29 02:12

    Simple helper function written in Kotlin.

    private fun Canvas.drawTopRoundRect(rect: RectF, paint: Paint, radius: Float) {
        // Step 1. Draw rect with rounded corners.
        drawRoundRect(rect, radius, radius, paint)
    
        // Step 2. Draw simple rect with reduced height,
        // so it wont cover top rounded corners.
        drawRect(
                rect.left,
                rect.top + radius,
                rect.right,
                rect.bottom,
                paint
        )
    }
    

    Usage:

    canvas.drawTopRoundRect(rect, paint, radius)
    
    0 讨论(0)
  • 2020-11-29 02:12

    This is an old question, however I wanted to add my solution because it uses the native SDK without lots of custom code or hacky drawing. This solution is supported back to API 1.

    The way to do this properly is to create a path (as mentioned in other answers) however the previous answers seem to overlook the addRoundedRect function call that takes radii for each corner.

    Variables

    private val path = Path()
    private val paint = Paint()
    

    Setup Paint

    paint.color = Color.RED
    paint.style = Paint.Style.FILL
    

    Update Path with Size Changes

    Call this somewhere that isn't onDraw, such as onMeasure for a view or onBoundChange for a drawable. If it doesn't change (like this example) you could put this code where you set up your paint.

    val radii = floatArrayOf(
        25f, 25f, //Top left corner
        25f, 25f, //Top right corner
        0f, 0f,   //Bottom right corner
        0f, 0f,   //Bottom left corner
    )
    
    path.reset() //Clears the previously set path
    path.addRoundedRect(0f, 0f, 100f, 100f, radii, Path.Direction.CW)
    

    This code creates a 100x100 rounded rect with the top corners rounded with a 25 radius.

    Draw Path

    Call this in onDraw for a view or draw for a drawable.

    canvas.drawPath(path, paint)
    
    0 讨论(0)
  • 2020-11-29 02:14

    I would draw two rectangles:

    canvas.drawRect(new RectF(0, 110, 100, 290), paint);
    canvas.drawRoundRect(new RectF(0, 100, 100, 200), 6, 6, paint);
    

    Or something like that, you just overlap them so that the upper corners will be round. Preferably you should write a method for this

    0 讨论(0)
  • 2020-11-29 02:14

    For API 21 and above the Path class added a new method addRoundRect() which you can use it like this.

    corners = new float[]{
        80, 80,        // Top left radius in px
        80, 80,        // Top right radius in px
        0, 0,          // Bottom right radius in px
        0, 0           // Bottom left radius in px
    };
    
    final Path path = new Path();
    path.addRoundRect(rect, corners, Path.Direction.CW);
    canvas.drawPath(path, mPaint);
    

    in Kotlin

    val corners = floatArrayOf(
        80f, 80f,   // Top left radius in px
        80f, 80f,   // Top right radius in px
        0f, 0f,     // Bottom right radius in px
        0f, 0f      // Bottom left radius in px
    )
    
    val path = Path()
    path.addRoundRect(rect, corners, Path.Direction.CW)
    canvas.drawPath(path, mPaint)
    
    0 讨论(0)
  • 2020-11-29 02:19

    draw round rect with left rounded corners

      private void drawRoundRect(float left, float top, float right, float bottom, Paint paint, Canvas canvas) {
            Path path = new Path();
            path.moveTo(left, top);
            path.lineTo(right, top);
            path.lineTo(right, bottom);
            path.lineTo(left + radius, bottom);
            path.quadTo(left, bottom, left, bottom - radius);
            path.lineTo(left, top + radius);
            path.quadTo(left, top, left + radius, top);
            canvas.drawPath(path, onlinePaint);
        }
    
    0 讨论(0)
  • 2020-11-29 02:20

    A Path#arcTo() version to draw the rounded side if the radius is half of the height.

    fun getPathOfRoundedRectF(
        rect: RectF,
        topLeftRadius: Float = 0f,
        topRightRadius: Float = 0f,
        bottomRightRadius: Float = 0f,
        bottomLeftRadius: Float = 0f
    ): Path {
        val tlRadius = topLeftRadius.coerceAtLeast(0f)
        val trRadius = topRightRadius.coerceAtLeast(0f)
        val brRadius = bottomRightRadius.coerceAtLeast(0f)
        val blRadius = bottomLeftRadius.coerceAtLeast(0f)
    
        with(Path()) {
            moveTo(rect.left + tlRadius, rect.top)
    
            //setup top border
            lineTo(rect.right - trRadius, rect.top)
    
            //setup top-right corner
            arcTo(
                RectF(
                    rect.right - trRadius * 2f,
                    rect.top,
                    rect.right,
                    rect.top + trRadius * 2f
                ), -90f, 90f
            )
    
            //setup right border
            lineTo(rect.right, rect.bottom - trRadius)
    
            //setup bottom-right corner
            arcTo(
                RectF(
                    rect.right - brRadius * 2f,
                    rect.bottom - brRadius * 2f,
                    rect.right,
                    rect.bottom
                ), 0f, 90f
            )
    
            //setup bottom border
            lineTo(rect.left + blRadius, rect.bottom)
    
            //setup bottom-left corner
            arcTo(
                RectF(
                    rect.left,
                    rect.bottom - blRadius * 2f,
                    rect.left + blRadius * 2f,
                    rect.bottom
                ), 90f, 90f
            )
    
            //setup left border
            lineTo(rect.left, rect.top + tlRadius)
    
            //setup top-left corner
            arcTo(
                RectF(
                    rect.left,
                    rect.top,
                    rect.left + tlRadius * 2f,
                    rect.top + tlRadius * 2f
                ),
                180f,
                90f
            )
    
            close()
    
            return this
        }
    }
    

    0 讨论(0)
提交回复
热议问题