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
I achieved this by following the below steps.
These are the pre-requisites for the rounded rectangle to look neat
Next is the steps to draw the rounded rectangle.
First we draw 2 circles on the left and right side, with the radius = height of rectange / 2
Then we draw a rectangle between these circles to get the desired rounded rectangle.
I am posting the code below
private void drawRoundedRect(Canvas canvas, float left, float top, float right, float bottom) {
float radius = getHeight() / 2;
canvas.drawCircle(radius, radius, radius, mainPaint);
canvas.drawCircle(right - radius, radius, radius, mainPaint);
canvas.drawRect(left + radius, top, right - radius, bottom, mainPaint);
}
Now this results in a really nice rounded rectangle like the one shown below
One simple and efficient way to draw a solid side is to use clipping - rect clipping is essentially free, and a lot less code to write than a custom Path.
If I want a 300x300 rect, with the top left and right rounded by 50 pixels, you can do:
canvas.save();
canvas.clipRect(0, 0, 300, 300);
canvas.drawRoundRect(new RectF(0, 0, 300, 350), 50, 50, paint);
canvas.restore();
This approach will only work for rounding on 2 or 3 adjacent corners, so it's a little less configurable than a Path based approach, but using round rects is more efficient, since drawRoundRect() is fully hardware accelerated (that is, tessellated into triangles) while drawPath() always falls back to software rendering (software-draw a path bitmap, and upload that to be cached on the GPU).
Not a huge performance issue for small infrequent drawing, but if you're animating paths, the cost of software draw can make your frame times longer, and increase your chance to drop frames. The path mask also costs memory.
If you do want to go with a Path-based approach, I'd recommend using GradientDrawable to simplify the lines of code (assuming you don't need to set a custom shader, e.g. to draw a Bitmap).
mGradient.setBounds(0, 0, 300, 300);
mGradient.setCornerRadii(new int[] {50,50, 50,50, 0,0, 0,0});
With GradientDrawable#setCornerRadii(), you can set any corner to be any roundedness, and reasonably animate between states.
I changed this answer so you can set which corner you want to be round and which one you want to be sharp. also works on pre-lolipop
Usage Example:only top-right and botton-right corners are rounded
Path path = RoundedRect(0, 0, fwidth , fheight , 5,5,
false, true, true, false);
canvas.drawPath(path,myPaint);
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl
){
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);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else{
path.rLineTo(0, -ry);
path.rLineTo(-rx,0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else{
path.rLineTo(-rx, 0);
path.rLineTo(0,ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else{
path.rLineTo(0, ry);
path.rLineTo(rx,0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else{
path.rLineTo(rx,0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
Use PaintDrawable could be better:
val topLeftRadius = 10
val topRightRadius = 10
val bottomLeftRadius = 0
val bottomRightRadius = 0
val rect = Rect(0, 0, 100, 100)
val paintDrawable = PaintDrawable(Color.RED)
val outter = floatArrayOf(topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
bottomLeftRadius, bottomLeftRadius, bottomRightRadius, bottomRightRadius)
paintDrawable.setCornerRadii(outter)
paintDrawable.bounds = rect
paintDrawable.draw(canvas)
you can easily achieve this by using Path:
val radiusArr = floatArrayOf(
15f, 15f,
15f, 15f,
0f, 0f,
0f, 0f
)
val myPath = Path()
myPath.addRoundRect(
RectF(0f, 0f, 400f, 400f),
radiusArr,
Path.Direction.CW
)
canvas.drawPath(myPath, paint)
You can draw that piece by piece using drawLine()
and drawArc()
functions from the Canvas
.