Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 RectF(0, 100, 100, 300), 6, 6, paint); 
like image 560
virsir Avatar asked May 05 '11 10:05

virsir


People also ask

How do I make rounded corners on Canvas?

With canvas, use the rect() method to draw a rectangle. But, for creating a rounded rectangle, using the rect() method won't work. We will be using the lineTo() and quadraticCurveTo() method to create a rounded rectangle.


1 Answers

Use a path. It has the advantage of working for APIs less than 21 (Arc is also limited thusly, which is why I quad). Which is a problem because not everybody has Lollipop yet. You can however specify a RectF and set the values with that and use arc back to API 1, but then you wouldn't get to use a static (without declaring a new object to build the object).

Drawing a rounded rect:

    path.moveTo(right, top + ry);     path.rQuadTo(0, -ry, -rx, -ry);     path.rLineTo(-(width - (2 * rx)), 0);     path.rQuadTo(-rx, 0, -rx, ry);     path.rLineTo(0, (height - (2 * ry)));     path.rQuadTo(0, ry, rx, ry);     path.rLineTo((width - (2 * rx)), 0);     path.rQuadTo(rx, 0, rx, -ry);     path.rLineTo(0, -(height - (2 * ry)));     path.close(); 

As a full function:

static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {     Path path = new Path();     if (rx < 0) rx = 0;     if (ry < 0) ry = 0;     float width = right - left;     float height = bottom - top;     if (rx > width/2) rx = width/2;     if (ry > height/2) ry = height/2;     float widthMinusCorners = (width - (2 * rx));     float heightMinusCorners = (height - (2 * ry));      path.moveTo(right, top + ry);     path.rQuadTo(0, -ry, -rx, -ry);//top-right corner     path.rLineTo(-widthMinusCorners, 0);     path.rQuadTo(-rx, 0, -rx, ry); //top-left corner     path.rLineTo(0, heightMinusCorners);      if (conformToOriginalPost) {         path.rLineTo(0, ry);         path.rLineTo(width, 0);         path.rLineTo(0, -ry);     }     else {         path.rQuadTo(0, ry, rx, ry);//bottom-left corner         path.rLineTo(widthMinusCorners, 0);         path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner     }      path.rLineTo(0, -heightMinusCorners);      path.close();//Given close, last lineto can be removed.      return path; } 

You'd want to line all the way to those corner bits, rather than quad across them. This is what setting true to conformToOriginalPost does. Just line to the control point there.

If you want to do that all but don't care about pre-Lollipop stuff, and urgently insist that if your rx and ry are high enough, it should draw a circle.

@TargetApi(Build.VERSION_CODES.LOLLIPOP) static public Path RoundedRect(float left, float top, float right, float bottom, float rx, float ry, boolean conformToOriginalPost) {     Path path = new Path();     if (rx < 0) rx = 0;     if (ry < 0) ry = 0;     float width = right - left;     float height = bottom - top;     if (rx > width/2) rx = width/2;     if (ry > height/2) ry = height/2;     float widthMinusCorners = (width - (2 * rx));     float heightMinusCorners = (height - (2 * ry));      path.moveTo(right, top + ry);     path.arcTo(right - 2*rx, top, right, top + 2*ry, 0, -90, false); //top-right-corner     path.rLineTo(-widthMinusCorners, 0);     path.arcTo(left, top, left + 2*rx, top + 2*ry, 270, -90, false);//top-left corner.     path.rLineTo(0, heightMinusCorners);     if (conformToOriginalPost) {         path.rLineTo(0, ry);         path.rLineTo(width, 0);         path.rLineTo(0, -ry);     }     else {         path.arcTo(left, bottom - 2 * ry, left + 2 * rx, bottom, 180, -90, false); //bottom-left corner         path.rLineTo(widthMinusCorners, 0);         path.arcTo(right - 2 * rx, bottom - 2 * ry, right, bottom, 90, -90, false); //bottom-right corner     }      path.rLineTo(0, -heightMinusCorners);      path.close();//Given close, last lineto can be removed.     return path; } 

So, conformToOriginalPost actually draws a rounded rect without the bottom two bits rounded.

arcquadimage

like image 84
Tatarize Avatar answered Sep 21 '22 11:09

Tatarize