Search code examples
androidbitmapdrawablenine-patchandroid-seekbar

SeekBar: getting empty bitmap from Drawable until set it to ImageView OR how to get resulting Bitmap from 9patch


So I want to set a Bitmap created from drawable into a SeekBar's progress. And I make it so:

    Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    Drawable drawable = getResources().getDrawable(R.drawable.seekbar_bg_full);
    Canvas canvas = new Canvas(bmp);
    drawable.setBounds(0, 0, width, height);
    drawable.draw(canvas); // I assume here drawable must be drawn but its not
    // canvas.drawBitmap(bmp, 0 , 0, null); // does nothing as 4 me
    // encode/decode to detach bitmap from 9patch
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bmp.compress(CompressFormat.PNG, 0, baos);
    final byte[] bytes = baos.toByteArray();
    bmp.recycle();
    bmp = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
    // ClipDrawable is intented to be used as progressDrawable in SeekBar
    ClipDrawable progressDrawable = new ClipDrawable(new BitmapDrawable(getResources(),bmp), Gravity.LEFT, ClipDrawable.HORIZONTAL);
    // if not set this drawable to an ImageView then no progress will be shown by SeekBar at all
    //ImageView imgFake = (ImageView) findViewById(R.id.fakeImageView);
    //imgFake.setImageDrawable(progressDrawable);
    mySeekBar.setProgressDrawable(progressDrawable);

width and height are valid values here (like 460 and 30). As you can see there are 2 code lines about ImageView are commented. This ImageView persists on a layout and its visibility is INVISIBLE. If I comment those 2 lines like shown then there will be no visible progress, like drawable is empty or transparent. Looks like this ImageView makes drawable to really draw itself. But I don't like to use a fake ImageView just to make the "magic" happen so the question is - how to make it work without this fake ImageView.
Please don't suggest me ways how to properly set SeekBar progress like:

ClipDrawable progressDrawable = new ClipDrawable(getResources().getDrawable(R.drawable.seekbar_bg_full), Gravity.LEFT, ClipDrawable.HORIZONTAL);
mySeekBar.setProgressDrawable(progressDrawable);

or xml selectors ways or any altrnative ways since I know about it already and my quiestion is not really about it. I just need to make it work my way.
I just need to make my bitmap or canvas or whatever really drawn.
A bit more details if you want (optional to read). The problem is about the drawable seekbar_bg_full - its a 9-patch png. And all need is to obtain a not NinePatchDrawable-linked resulting Bitmap. Assume I have a 460x30px view with 9patch image set as src or background and the 9patch image is stretched just like it should to. So I need to get a Bitmap this view contains and this Bitmap should not be linked somehow to a 9patch. Thats why I encode bitmap to an byte-array and then decode it back - its just to get rid of 9patch. If there is a more esay way to get a resulting bitmap from 9patch (some magic around NinePatchDrawable) - I would like to know about it.


Solution

  • Ok, I figured out how to get rid of fake ImageView and make drawable to draw itself: all I have to do is to call setBounds() method on a drawable:

    ClipDrawable progressDrawable = new ClipDrawable(new BitmapDrawable(getResources(),bmp), Gravity.LEFT, ClipDrawable.HORIZONTAL);
    progressDrawable.setBounds(0, 0, width, height);
    mySeekBar.setProgressDrawable(progressDrawable);
    

    Now I don't have to use ImageView, at last!
    However my code is a really long story to get rid of 9patch features in drawable.