1、Xfermode
绘制两层,先绘制形状,再绘制图片,然后根据Xfermode来去计算两个图层的关系(SRC_IN:显示的区域是二者交集)。
Glide实现圆形图片
static {
CIRCLE_CROP_BITMAP_PAINT = new Paint(CIRCLE_CROP_PAINT_FLAGS);
CIRCLE_CROP_BITMAP_PAINT.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
}
/**
* Crop the image to a circle and resize to the specified width/height. The circle crop will
* have the same width and height equal to the min-edge of the result image.
*
* @param pool The BitmapPool obtain a bitmap from.
* @param inBitmap The Bitmap to resize.
* @param destWidth The width in pixels of the final Bitmap.
* @param destHeight The height in pixels of the final Bitmap.
* @return The resized Bitmap (will be recycled if recycled is not null).
*/
public static Bitmap circleCrop(@NonNull BitmapPool pool, @NonNull Bitmap inBitmap,
int destWidth, int destHeight) {
int destMinEdge = Math.min(destWidth, destHeight);
float radius = destMinEdge / 2f;
int srcWidth = inBitmap.getWidth();
int srcHeight = inBitmap.getHeight();
float scaleX = destMinEdge / (float) srcWidth;
float scaleY = destMinEdge / (float) srcHeight;
float maxScale = Math.max(scaleX, scaleY);
float scaledWidth = maxScale * srcWidth;
float scaledHeight = maxScale * srcHeight;
float left = (destMinEdge - scaledWidth) / 2f;
float top = (destMinEdge - scaledHeight) / 2f;
RectF destRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);
// Alpha is required for this transformation.
Bitmap toTransform = getAlphaSafeBitmap(pool, inBitmap);
Bitmap result = pool.get(destMinEdge, destMinEdge, Bitmap.Config.ARGB_8888);
result.setHasAlpha(true);
BITMAP_DRAWABLE_LOCK.lock();
try {
Canvas canvas = new Canvas(result);
// Draw a circle
canvas.drawCircle(radius, radius, radius, CIRCLE_CROP_SHAPE_PAINT);
// Draw the bitmap in the circle
canvas.drawBitmap(toTransform, null, destRect, CIRCLE_CROP_BITMAP_PAINT);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
}
if (!toTransform.equals(inBitmap)) {
pool.put(toTransform);
}
return result;
}
2、BitmapShader
将drawable转化为bitmap,然后直接初始化BitmapShader,画笔设置Shader,最后在onDraw里面进行画圆。
/**
* Creates a bitmap from a source bitmap and rounds the corners.
*
* <p>This method does <em>NOT</em> resize the given {@link Bitmap}, it only rounds it's corners.
* To both resize and round the corners of an image, consider
* {@link com.bumptech.glide.request.RequestOptions#transforms(Transformation[])} and/or
* {@link com.bumptech.glide.load.MultiTransformation}.
*
* @param inBitmap the source bitmap to use as a basis for the created bitmap.
* @param roundingRadius the corner radius to be applied (in device-specific pixels).
* @return a {@link Bitmap} similar to inBitmap but with rounded corners.
* @throws IllegalArgumentException if roundingRadius, width or height is 0 or less.
*/
public static Bitmap roundedCorners(
@NonNull BitmapPool pool, @NonNull Bitmap inBitmap, int roundingRadius) {
Preconditions.checkArgument(roundingRadius > 0, "roundingRadius must be greater than 0.");
// Alpha is required for this transformation.
Bitmap toTransform = getAlphaSafeBitmap(pool, inBitmap);
Bitmap result =
pool.get(toTransform.getWidth(), toTransform.getHeight(), Bitmap.Config.ARGB_8888);
result.setHasAlpha(true);
BitmapShader shader = new BitmapShader(toTransform, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
RectF rect = new RectF(0, 0, result.getWidth(), result.getHeight());
BITMAP_DRAWABLE_LOCK.lock();
try {
Canvas canvas = new Canvas(result);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawRoundRect(rect, roundingRadius, roundingRadius, paint);
clear(canvas);
} finally {
BITMAP_DRAWABLE_LOCK.unlock();
}
if (!toTransform.equals(inBitmap)) {
pool.put(toTransform);
}
return result;
}
3、clipPath
clipPath方法会将绘制的图形裁剪下来,然后再把图片画上去。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic);
mPath = new Path();
mPath.addCircle(mBitmap.getWidth() / 2, mBitmap.getHeight() / 2, mBitmap.getWidth() / 2, Path.Direction.CCW);
canvas.clipPath(mPath);
canvas.drawBitmap(mBitmap, 0, 0, paint);
}