Monday, 21 January 2013

Custom seek-bar like Circle (pie chart) using bitmap.

Here's something I came up with using clip path. I'm using following images (coder colours) out of which background is a solid one and foreground one contains only blue circle on transparent background. First background image is drawn onto screen, then clip path is set so that progress image, foreground one, is drawn properly on top of it.


private class ProgressView extends View {

    private Bitmap bgBitmap;
    private Bitmap fgBitmap;
    private RectF fullRect = new RectF();
    private Path clipPath = new Path();

    public ProgressView(Context context) {
        super(context);
        bgBitmap = BitmapFactory.decodeResource(
                                   context.getResources(), R.drawable.bg);
        fgBitmap = BitmapFactory.decodeResource(
                                   context.getResources(), R.drawable.fg);
    }

    @Override
    public void onDraw(Canvas c) {
        fullRect.right = getWidth();
        fullRect.bottom = getHeight();

        c.drawBitmap(bgBitmap, null, fullRect, null);

        float angle = SystemClock.uptimeMillis() % 3600 / 10.0f;

        clipPath.reset();
        clipPath.setLastPoint(getWidth() / 2, getHeight() / 2);
        clipPath.lineTo(getWidth() / 2, getHeight());
        clipPath.arcTo(fullRect, -90, angle);
        clipPath.lineTo(getWidth() / 2, getHeight() / 2);
        c.clipPath(clipPath);

        c.drawBitmap(fgBitmap, null, fullRect, null);

        invalidate();
    }   
}

also we can achieved like as seek-bar on touch event of this custom view.

@Override
public boolean onTouchEvent(MotionEvent event) {
int touchX = (int) event.getX();
int touchY = (int) event.getY();

if (outerCircle == null) {
 return true; // ignore all events until the canvas is drawn
}
float x1 = bgBitmap.getWidth(), x2 = bgBitmap.getHeight(), y1 = bgBitmap
    .getWidth(), y2 = bgBitmap.getHeight();
if ((touchX <= x1 && touchX <= x2)
  && (touchY <= y1 && touchY <= y2)) {
int angle = pointToAngle(touchX, touchY);
// model.rotate(Integer.valueOf(""+Math.round((angle / 3.6))));
angle = 360 + angle - startAngle;
int angleX2 = angle * 2;
angleX2 = roundToNearest15(angleX2);
if (angleX2 > 720) {
 angleX2 = angleX2 - 720; // avoid mod because we prefer 720 over
 }
 
 setMinutes(angleX2);
model.rotate(Integer.valueOf("" + Math.round((angleX2 / 7.2))));
 return true;
} else {
 return false;
 }
}

No comments:

Post a Comment