Draw a semicircle in the background of a View
To clip the oval shape, just embed it in a ClipDrawable like this:
res/drawable/semicircle.xml
<?xml version="1.0" encoding="utf-8"?>
<clip
xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:gravity="bottom">
<shape android:shape="oval">
<solid android:color="#444"/>
</shape>
</clip>
ClipDdrawable
common purpose is to create custom progress bars. It clips a part of its content and progressively displays it when its "level" property increases in a range of [0; 10000] (0=hidden, 10000=fully displayed).
clipOrientation
is the orientation of the clipping progress.gravity
is the clipping progress start edge/side.
To get a half circle, set this ClipDrawable
as your view background, and programmatically tweak its "level":
//...
findViewById(R.id.my_view).getBackground().setLevel(5000)
//...
Works on all Android versions ("Added in API level 1") and requires no custom view.
;-)
You can implement you own Drawable. But that cannot be inflated from XML. You need to set the drawable from code using View.setBackgroundDrawable();
See my sample implementation to draw a semi circle using drawable.
public class SemiCircleDrawable extends Drawable {
private Paint paint;
private RectF rectF;
private int color;
private Direction angle;
public enum Direction
{
LEFT,
RIGHT,
TOP,
BOTTOM
}
public SemiCircleDrawable() {
this(Color.BLUE, Direction.LEFT);
}
public SemiCircleDrawable(int color, Direction angle) {
this.color = color;
this.angle = angle;
paint = new Paint();
paint.setColor(color);
paint.setStyle(Style.FILL);
paint.setAntiAlias(true);
rectF = new RectF();
}
public int getColor() {
return color;
}
/**
* A 32bit color not a color resources.
* @param color
*/
public void setColor(int color) {
this.color = color;
paint.setColor(color);
}
@Override
public void draw(Canvas canvas) {
canvas.save();
Rect bounds = getBounds();
if(angle == Direction.LEFT || angle == Direction.RIGHT)
{
canvas.scale(2, 1);
if(angle == Direction.RIGHT)
{
canvas.translate(-(bounds.right / 2), 0);
}
}
else
{
canvas.scale(1, 2);
if(angle == Direction.BOTTOM)
{
canvas.translate(0, -(bounds.bottom / 2));
}
}
rectF.set(bounds);
if(angle == Direction.LEFT)
canvas.drawArc(rectF, 90, 180, true, paint);
else if(angle == Direction.TOP)
canvas.drawArc(rectF, -180, 180, true, paint);
else if(angle == Direction.RIGHT)
canvas.drawArc(rectF, 270, 180, true, paint);
else if(angle == Direction.BOTTOM)
canvas.drawArc(rectF, 0, 180, true, paint);
canvas.restore()
}
@Override
public void setAlpha(int alpha) {
// Has no effect
}
@Override
public void setColorFilter(ColorFilter cf) {
// Has no effect
}
@Override
public int getOpacity() {
// Not Implemented
return PixelFormat.UNKNOWN;
}
}