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.
Images can be rounded in two shapes:
- As a circle - set
- As a rectangle, but with rounded corners. Set
roundedCornerRadiusto 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.
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 than
fit_xy. If you use this rounding method with other scale types, such as
center, 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. Use
roundWithOverlayColorin XML, or
setOverlayColorin code to use this rounding method.
SimpleDraweeView class will forward several attributes over to
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" >
When constructing a hierarchy, you can pass an instance of RoundingParams to your
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);
There are some limitations when
BITMAP_ONLY (the default) mode is used:
- Only images that resolve to
ColorDrawablecan be rounded. Rounding
ShapeDrawableand 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.
For a full sample see the
DraweeRoundedCornersFragment in the showcase app: DraweeRoundedCornersFragment.java