0

I'm trying to fill a round circle (transparent other than the outline of the circle) in an ImageView.

I have the code working:

public void setPercentage(int p) {
    if (this.percentage != p ) {
   this.percentage = p;
    this.invalidate();
   }
}
@Override public void onDraw(Canvas canvas) {
 Canvas tempCanvas;
        Paint paint;    
        Bitmap bmCircle = null;
        if (this.getWidth() == 0 || this.getHeight() == 0 ) 
            return ; // nothing to do
        mergedLayersBitmap = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888); 

        tempCanvas = new Canvas(mergedLayersBitmap);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setFilterBitmap(false);



        bmCircle = drawCircle(this.getWidth(), this.getHeight());

        tempCanvas.drawBitmap(bmCircle, 0, 0, paint);


        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        tempCanvas.clipRect(0,0, this.getWidth(), (int) FloatMath.floor(this.getHeight() - this.getHeight() * ( percentage/100)));
        tempCanvas.drawColor(0xFF660000, PorterDuff.Mode.CLEAR);  

        canvas.drawBitmap(mergedLayersBitmap, null, new RectF(0,0, this.getWidth(), this.getHeight()), new Paint());
        canvas.drawBitmap(mergedLayersBitmap, 0, 0, new Paint());

    }
  static Bitmap drawCircle(int w, int h) {
        Bitmap bm = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bm);
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);

        p.setColor(drawColor);    
        c.drawOval(new RectF(0, 0, w, h), p);
        return bm;

    }

It kind of works. However, I have two issues: I run out of memory quickly and the GC goes crazy. How can I utilize the least amount of memory for this operation?

I know I Shouldn't be instantiating objects in onDraw, however I'm not sure where to draw then. Thank you.

StackOverflowed
  • 5,854
  • 9
  • 55
  • 119
  • Could you just use the same `Canvas`, `mergedLayersBitmap`, etc, between successive calls to `onDraw()`? You can still draw but lose the allocation... – Rob I Aug 11 '12 at 23:58
  • Why can't you actually use the progress bar with circle as "mask"? I think it should work as you could make the progress bar a square with rounded corners:) – Lukasz 'Severiaan' Grela Feb 04 '14 at 10:14

2 Answers2

2

pseudo would look something like this.

    for each pixel inside CircleBitmap {

        if (pixel.y is < Yboundary && pixelIsInCircle(pixel.x, pixel.y)) {
           CircleBitmap .setPixel(x, y, Color.rgb(45, 127, 0));
        }
    }

that may be slow, but it would work, and the smaller the circle the faster it would go.

just know the basics, bitmap width and height, for example 256x256, the circles radius, and to make things easy make the circle centered at 128,128. then as you go pixel by pixel, check the pixels X and Y to see if it falls inside the circle, and below the Y limit line.

then just use:

    CircleBitmap .setPixel(x, y, Color.rgb(45, 127, 0));

edit: to speed things up, don't even bother looking at the pixels above the Y limit.

WIllJBD
  • 6,144
  • 3
  • 34
  • 44
2

in case if you want to see another solution (perhaps cleaner), look at this link, filling a circle gradually from bottom to top android

Community
  • 1
  • 1
Kaps
  • 2,345
  • 2
  • 26
  • 37