如何通过编程为Drawable对象(应用图标)设置圆角或圆形样式?
当然可行!我之前在项目里刚好处理过类似的需求,不管是你已经获取到的应用启动器Drawable,还是其他任意Drawable,都能轻松把它改成圆形或者圆角样式,下面给你两种实用的实现方案:
方案一:自定义RoundDrawable类(灵活可控)
这种方法是通过自定义Drawable子类,利用BitmapShader来实现圆形/圆角效果,好处是可以直接复用,还能动态调整圆角大小。
实现步骤:
- 创建
RoundDrawable类,继承自Drawable,核心是在onDraw()方法里用Shader绘制带圆角的图形:
public class RoundDrawable extends Drawable { private Paint mPaint; private Bitmap mBitmap; private RectF mRectF; private float mRadius; // 圆角半径,设为Bitmap宽高一半就是圆形 public RoundDrawable(Bitmap bitmap, float radius) { mBitmap = bitmap; mRadius = radius; BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setShader(shader); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); mRectF = new RectF(bounds); } @Override public void draw(@NonNull Canvas canvas) { // 绘制圆角矩形,mRadius设为宽高一半就是圆形 canvas.drawRoundRect(mRectF, mRadius, mRadius, mPaint); } @Override public void setAlpha(int alpha) { mPaint.setAlpha(alpha); invalidateSelf(); } @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { mPaint.setColorFilter(colorFilter); invalidateSelf(); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } // 提供静态方法,直接将Drawable转为RoundDrawable public static RoundDrawable fromDrawable(Drawable drawable, float radius) { if (drawable instanceof BitmapDrawable) { return new RoundDrawable(((BitmapDrawable) drawable).getBitmap(), radius); } // 非BitmapDrawable的情况,先转成Bitmap Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return new RoundDrawable(bitmap, radius); } }
- 使用的时候,直接把你拿到的启动器Drawable传进去就行:
// 假设你已经获取到了应用的启动器Drawable:appIconDrawable // 转成圆形(圆角半径设为宽高的一半) float radius = Math.min(appIconDrawable.getIntrinsicWidth(), appIconDrawable.getIntrinsicHeight()) / 2f; RoundDrawable roundIcon = RoundDrawable.fromDrawable(appIconDrawable, radius); // 如果要转成圆角矩形,比如16dp的圆角 float dp16 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()); RoundDrawable roundedCornerIcon = RoundDrawable.fromDrawable(appIconDrawable, dp16); // 然后就可以把roundIcon设置给ImageView或者其他View了 imageView.setImageDrawable(roundIcon);
方案二:直接用Canvas裁剪(快速实现)
如果只是临时处理某个Drawable,不想写自定义类,可以直接把Drawable转为Bitmap,然后用Canvas的裁剪逻辑处理,再转成Drawable:
public static Drawable getRoundedDrawable(Drawable drawable, float radius) { Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); // 创建裁剪后的Bitmap Bitmap roundedBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas roundedCanvas = new Canvas(roundedBitmap); Paint paint = new Paint(); paint.setAntiAlias(true); RectF rectF = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); // 先绘制圆角路径,再用SRC_IN模式叠加原Bitmap roundedCanvas.drawRoundRect(rectF, radius, radius, paint); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); roundedCanvas.drawBitmap(bitmap, 0, 0, paint); return new BitmapDrawable(roundedBitmap); } // 使用示例: Drawable roundedIcon = getRoundedDrawable(appIconDrawable, dp16); imageView.setImageDrawable(roundedIcon);
注意事项:
- 如果你的Drawable是矢量图(VectorDrawable),转Bitmap的时候要注意设置正确的宽高,避免模糊;
- 两种方法都要记得处理
Bitmap的回收,避免内存泄漏,尤其是在列表中使用的时候; - 方案一的自定义Drawable更适合复用,比如在多个地方需要圆形/圆角图标时,推荐用这个方案。
内容的提问来源于stack exchange,提问作者java
相关产品推荐
相关产品推荐

