Using a rounded corners drawable

There is a nice post made by the popular Google developer Romain Guy that shows how to use a rounded corners drawable (called "StreamDrawable" in his code ) on a view efficiently.

The sample itself works very well on my Galaxy S3 when in portrait mode, but I have a few issues with it:

  • if the screen is small (for example on qvga screens), the shown images get cropped.

  • if I have an input bitmap that is too small than how I wish to show it, the output image has its edges smeared. Even on the Galaxy S3, when you run the sample code and it's on landscape, it looks awful:

    在这里输入图像描述

  • I'm still not sure about it (since I use a workaround of scaling the image for using the sample code), but it think that even this solution is a bit slow when being used in a listView. Maybe there is a renderscript solution for this?

  • It doesn't matter if I use setImageDrawable or setBackgroundDrawable. It must be something in the drawable itself.

    I've tried to play with the variables and the bitmapShader, but nothing worked. Sadly TileMode doesn't have a value for just stretching the image, only tiling it in some way.

    As a workaround I can create a new scaled bitmap, but it's just a workaround. Surely there is a better way which will also not use more memory than it should.

    How do I fix those issues and use this great code?


    I think that the solution that is presented on this website works well.

    unlike other solutions, it doesn't cause memory leaks, even though it is based on Romain Guy's solution.

    EDIT: now on the support library, you can also use RoundedBitmapDrawable (using RoundedBitmapDrawableFactory ) .


    I had some size issues with this code, and I solved it.

    Maybe this will help you, too:

    1) in the constructor store the bitmap in a local variable (eg private Bitmap bmp;)

    2) override two more methods:

    @Override
        public int getIntrinsicWidth() {
        return bmp.getWidth();
    }
    
    @Override
        public int getIntrinsicHeight() {
        return bmp.getHeight();
    }
    

    Best regards, DaRolla


    There underlying problem is that the BitmapShader's TileMode doesn't have a scaling option. You'll note in the source that it's been set to Shader.TileMode.CLAMP , and the docs describe that as:

    replicate the edge color if the shader draws outside of its original bounds

    To work around this, there are three solutions:

  • Constrain the size of the view in which the drawable is used to the size of the bitmap.
  • Constrain the drawing region; for instance, change:

    int width = bounds.width() - mMargin;
    int height = bounds.height() - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    

    To:

    int width = Math.min(mBitmap.getWidth(), bounds.width()) - mMargin;
    int height = Math.min(mBitmap.getHeight(), bounds.height()) - mMargin;
    mRect.set(mMargin, mMargin, width, height);
    
  • Scale the bitmap to the size of the drawable. I've moved creating the shader into onBoundsChange() and have opted to create a new bitmap from here:

    bitmap = Bitmap.createScaledBitmap(mBitmap, width, height, true);
    mBitmapShader = new BitmapShader(bitmap,
            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
    

    Note that this a potentially slow operation and will be running on the main thread. You might want to carefully consider how you want to implement it before you go for this last solution.

  • 链接地址: http://www.djcxy.com/p/31410.html

    上一篇: 如何使用RoundedBitmapDrawable

    下一篇: 使用可绘制的圆角