Rounded Corners and Circles
Not every image is a rectangle. Apps frequently need images that appear with softer, rounded corners, or as circles. Drawee supports a variety of scenarios, all without the memory overhead of copying bitmaps.
What
Images can be rounded in two shapes:
- As a circle - set
roundAsCircle
to true. - As a rectangle, but with rounded corners. Set
roundedCornerRadius
to some value.
Rectangles support having each of the four corners have a different radius, but this must be specified in Java code rather than XML.
How
Images can be rounded with two different methods:
BITMAP_ONLY
- Uses a bitmap shader to draw the bitmap with rounded corners. This is the default rounding method. It doesn’t support animations, and it does not support any scale types other thancenterCrop
(the default),focusCrop
andfit_xy
. If you use this rounding method with other scale types, such ascenter
, you won’t get an Exception but the image might look wrong (e.g. repeated edges due to how Android shaders work), especially in cases the source image is smaller than the view. See the Caveats section below.OVERLAY_COLOR
- Draws rounded corners by overlaying a solid color, specified by the caller. The Drawee’s background should be static and of the same solid color. UseroundWithOverlayColor
in XML, orsetOverlayColor
in code to use this rounding method.
In XML
The SimpleDraweeView
class will forward several attributes over to RoundingParams
:
1
2
3
4
5
6
7
8
9
<com.facebook.drawee.view.SimpleDraweeView
...
fresco:roundedCornerRadius="5dp"
fresco:roundBottomStart="false"
fresco:roundBottomEnd="false"
fresco:roundWithOverlayColor="@color/blue"
fresco:roundingBorderWidth="1dp"
fresco:roundingBorderColor="@color/red"
>
In code
When constructing a hierarchy, you can pass an instance of RoundingParams to your GenericDraweeHierarchyBuilder:
1
2
3
4
RoundingParams roundingParams = RoundingParams.fromCornersRadius(7f);
mSimpleDraweeView.setHierarchy(new GenericDraweeHierarchyBuilder(getResources())
.setRoundingParams(roundingParams)
.build());
You can also change all of the rounding parameters after the hierarchy has been built:
1
2
3
4
5
int color = getResources().getColor(R.color.red);
RoundingParams roundingParams = RoundingParams.fromCornersRadius(5f);
roundingParams.setBorder(color, 1.0f);
roundingParams.setRoundAsCircle(true);
mSimpleDraweeView.getHierarchy().setRoundingParams(roundingParams);
Caveats
There are some limitations when BITMAP_ONLY
(the default) mode is used:
- Only images that resolve to
BitmapDrawable
orColorDrawable
can be rounded. RoundingNinePatchDrawable
,ShapeDrawable
and other such drawables is not supported (regardless whether they are specified in XML or programmatically). - Animations are not rounded.
- Due to a limitation of Android’s
BitmapShader
, if the image doesn’t fully cover the view, instead of drawing nothing, edges are repeated. One workaround is to use a different scale type (e.g. centerCrop) that ensures that the whole view is covered. Another workaround is to make the image file contain a 1px transparent border so that the transparent pixels get repeated. This is the best solution for PNG resource images.
If the limitations of the BITMAP_ONLY
mode affect your images, see if the OVERLAY_COLOR
mode works for you. The OVERLAY_COLOR
mode doesn’t have the aforementioned limitations, but since it simulates rounded corners by overlaying a solid color over the image, this only looks good if the background under the view is static and of the same color.
Drawee internally has an implementation for CLIPPING
mode, but this mode has been disabled and not exposed as some Canvas
implementation do not support path clipping. Furthermore, canvas clipping doesn’t support antialiasing which makes the rounded edges very pixelated.
Finally, all of those issues could be avoided by using a temporary bitmap, but this imposes a significant memory overhead and has not been supported because of that.
As explained above, there is no really good solution for rounding corners on Android and one has to choose between the aforementioned trade-offs.
Full Sample
For a full sample see the DraweeRoundedCornersFragment
in the showcase app: DraweeRoundedCornersFragment.java