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 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.
上一篇: 如何使用RoundedBitmapDrawable
下一篇: 使用可绘制的圆角