Reputation: 13345
I want to draw on a canvas a round rectangle fill with color (or bitmap) and with a stroke but without some selected corners and also without the border on some selected sides. any ideas how i can achieve this ?
Upvotes: 2
Views: 3302
Reputation: 807
you can split the drawing process into two parts.
draw the fill area
when trying to draw a shape that is not support by the standard sdk APIs, Canvas.drawPath method will be a good way to do it.you can just define four variables to represent radiuses of four corners.
Path path = new Path();
Rect drawingRect = {the rect area you want to draw}
RectF topLeftArcBound = new RectF();
RectF topRightArcBound = new RectF();
RectF bottomLeftArcBound = new RectF();
RectF bottomRightArcBound = new RectF();
topRightArcBound.set(drawingRect.right - topRightRadius * 2, drawingRect.top, drawingRect.right, drawingRect.top + topRightRadius * 2);
bottomRightArcBound.set(drawingRect.right - bottomRightRadius * 2, drawingRect.bottom - bottomRightRadius * 2, drawingRect.right, drawingRect.bottom);
bottomLeftArcBound.set(drawingRect.left, drawingRect.bottom - bottomLeftRadius * 2, drawingRect.left + bottomLeftRadius * 2, drawingRect.bottom);
topLeftArcBound.set(drawingRect.left, drawingRect.top, drawingRect.left + topLeftRadius * 2, drawingRect.top + topLeftRadius * 2);
path.reset();
path.moveTo(drawingRect.left + topLeftRadius, drawingRect.top);
//draw top horizontal line
path.lineTo(drawingRect.right - topRightRadius, drawingRect.top);
//draw top-right corner
path.arcTo(topRightArcBound, -90, 90);
//draw right vertical line
path.lineTo(drawingRect.right, drawingRect.bottom - bottomRightRadius);
//draw bottom-right corner
path.arcTo(bottomRightArcBound, 0, 90);
//draw bottom horizontal line
path.lineTo(drawingRect.left - bottomLeftRadius, drawingRect.bottom);
//draw bottom-left corner
path.arcTo(bottomLeftArcBound, 90, 90);
//draw left vertical line
path.lineTo(drawingRect.left, drawingRect.top + topLeftRadius);
//draw top-left corner
path.arcTo(topLeftArcBound, 180, 90);
path.close();
paint.setStyle(Paint.Style.FILL);
canvas.drawPath(path, paint);
and you can just set radius to zero for selected corners
draw border
border contains eight parts:
use a int value to contains selected parts will be a good idea
private static final int TOP_LEFT_CORNER = 0x1; private static final int TOP_LINE = 0x2; private static final int TOP_RIGHT_CORNER = 0x4; private static final int RIGHT_LINE = 0x8; private static final int BOTTOM_RIGHT_CORNER = 0x10; private static final int BOTTOM_LINE = 0x20; private static final int BOTTOM_LEFT_CORNER = 0x40; private static final int LEFT_LINE = 0x80; private int selectedParts = TOP_LEFT_CORNER | TOP_LINE | TOP_RIGHT_CORNER;
and now we can draw border based on selectedParts:
paint.setStyle(Paint.Style.STROKE); if((selectedParts & TOP_LINE) > 0){ canvas.drawLine(drawingRect.left + topLeftRadius, drawingRect.top, drawingRect.right - topRightRadius, drawingRect.top); } if((selectedParts & TOP_RIGHT_CORNER) > 0){ canvas.drawArc(topRightArcBound, -90, 90, false, paint); } if((selectedParts & RIGHT_LINE) > 0){ canvas.drawLine(drawingRect.right, drawingRect.top + topRightRadius, drawingRect.right, drawingRect.bottom - bottomRightRadius, paint); } if((selectedParts & BOTTOM_RIGHT_CORNER) > 0){ canvas.drawArc(bottomRightArcBound, 0, 90, false, paint); } if((selectedParts & BOTTOM_LINE) > 0){ canvas.drawLine(drawingRect.right - bottomRightRadius, drawingRect.bottom. drawingRect.left + bottomLeftRadius, drawingRect.bottom, paint); } if((selectedParts & BOTTOM_LEFT_CORNER) > 0){ canvas.drawArc(bottomLeftArcBound, 90, 90, false, paint); } if((selectedParts & LEFT_LINE) > 0){ canvas.drawLine(drawingRect.left, drawingRect.bottom - bottomLeftRadius, drawingRect.left, drawingRect.top + topLeftRadius, paint); } if((selectedParts & TOP_LEFT_CORNER) > 0){ canvas.drawArc(topLeftArcBound, 180, 90, false, paint); }
Upvotes: 9