Reputation: 473
I am not very familiar with drawing tottally custom views in Android so I would need few pointers. Basically I would like to draw this view shown below:
So what I did was to draw a circle with a Paint:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(50);
But then I got completely lost when it came to adding the dashes evenly spaced with a top, bottom, left and right dash longer.
Can anyone give me a hint of how to approach this please?
Upvotes: 0
Views: 1377
Reputation: 13437
(1) One approach is to draw the thick black circle, then draw small white lines on top. Compute all the line endpoints using either trig or a DDA, or use a rotation matrix.
Call clipPath()
before drawing the lines so they'll stop cleanly at the outer edge of the circle.
(2) It's probably easier to use a DashPathEffect to draw circles with a dashed line: drawCircle(float cx, float cy, float radius, Paint paint)
.
With this approach, draw the outer ring of the circle using a dashed path effect with short dashes, then draw then middle ring using a dashed path effect with long dashes, and finally draw the inner ring using a solid paint.
You'll need to compute the right DashPathEffect
intervals (an off distance and an on distance) that gives the right "line" thickness, distance between "lines", and matches up at the end of the circle.
Upvotes: 0
Reputation: 134714
You really wouldn't even need to use a custom view for this (although if it starts to have behavior, you probably should move to one). Just make a custom drawable, and draw to the canvas as needed. A working example is below, with some commented caveats.
Basically, just draw the ring (just draw a circle with a thick stroke), then draw a tick on the bottom of the canvas, then continue rotating the canvas for each additional tick.
public class ClockDrawable extends Drawable {
// TODO Sample variables, these don't take density into account
private static final int TICK_COUNT = 48;
private static final int RING_THICKNESS = 50;
private static final int TICK_THICKNESS = 10;
private static final int LONG_TICK = 30;
private static final int SHORT_TICK = 10;
private final Paint mRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public ClockDrawable() {
mRingPaint.setColor(Color.BLACK);
mRingPaint.setStrokeWidth(RING_THICKNESS);
mRingPaint.setStyle(Style.STROKE);
mTickPaint.setColor(Color.WHITE);
mTickPaint.setStrokeWidth(TICK_THICKNESS);
mTickPaint.setStyle(Style.STROKE);
}
@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
final int h = bounds.height();
final float cx = bounds.exactCenterX();
final float cy = bounds.exactCenterY();
final float rotationAnglePerTick = 360f / TICK_COUNT;
// Draw the ring (using the stroke, offset by half of the stroke width
// since the stroke is drawn around the circle (not inside or outside)
canvas.drawCircle(cx, cy, cx - (mRingPaint.getStrokeWidth() / 2), mRingPaint);
for (int i = 0; i < TICK_COUNT; i++) {
// Check if it's one of the ticks on the top, left, right, or bottom
float tickHeight = i % (TICK_COUNT / 4) == 0 ? LONG_TICK : SHORT_TICK;
// For each tick, rotate the canvas by the angle per tick and the tick
// number, then draw a rectangle along the bottom. Since the canvas is
// rotating, you can just continue to draw a simple rectangle and not
// worry about angles. The canvas should rotate around the center point.
//
// Not covered here: clipping the ticks to stay within the ring bounds.
canvas.save();
canvas.rotate(rotationAnglePerTick * i, cx, cy);
canvas.drawRect(
cx - (TICK_THICKNESS / 2),
h - tickHeight,
cx + (TICK_THICKNESS / 2),
h,
mTickPaint);
canvas.restore();
}
}
@Override
public void setAlpha(int alpha) {
mRingPaint.setAlpha(alpha);
mTickPaint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter cf) {
mRingPaint.setColorFilter(cf);
mTickPaint.setColorFilter(cf);
invalidateSelf();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}
Upvotes: 3