Android低版本设备(Build.VERSION.SDK_INT < 21)如何实现canvas.drawRoundRect()绘制?
在Android API <21设备上绘制圆角矩形的可行方案
当然可以实现!哪怕在Android 5.0(API 21)之前的老旧设备上,我们依然有多种可靠的方式绘制圆角矩形,下面分享三个最实用的方案,覆盖不同场景需求:
方案一:手动拼接Path绘制(最灵活)
这种方法通过Path对象手动构建圆角矩形的轮廓,完全不依赖高版本API,兼容性拉满。核心思路是用直线连接四个边,再用圆弧拼接四个角,适合需要自定义路径逻辑的场景:
步骤拆解:
- 先定义矩形的边界(
left,top,right,bottom)和圆角半径radius - 创建
Path对象,按顺时针顺序绘制每条边和对应圆角:- 从右上角圆角的起始点开始,绘制上边线段
- 添加右上角的90度圆弧
- 绘制右边线段到右下角圆角起始点
- 添加右下角的90度圆弧
- 绘制下边线段到左下角圆角起始点
- 添加左下角的90度圆弧
- 绘制左边线段到左上角圆角起始点
- 添加左上角的90度圆弧,最后闭合路径
代码示例:
public void drawRoundRect(Canvas canvas, Paint paint, float left, float top, float right, float bottom, float radius) { Path path = new Path(); // 右上角圆弧 path.moveTo(right - radius, top); path.arcTo(right - 2 * radius, top, right, top + 2 * radius, 0, 90); // 右边直线 path.lineTo(right, bottom - radius); // 右下角圆弧 path.arcTo(right - 2 * radius, bottom - 2 * radius, right, bottom, 90, 90); // 下边直线 path.lineTo(left + radius, bottom); // 左下角圆弧 path.arcTo(left, bottom - 2 * radius, left + 2 * radius, bottom, 180, 90); // 左边直线 path.lineTo(left, top + radius); // 左上角圆弧 path.arcTo(left, top, left + 2 * radius, top + 2 * radius, 270, 90); // 闭合路径,确保图形完整 path.close(); canvas.drawPath(path, paint); }
小贴士:
arcTo()方法从API 1就存在,完全兼容低版本,参数分别对应圆弧的外接矩形、起始角度、扫过角度,刚好适配每个角的90度圆弧。
方案二:使用系统自带的RoundRectShape(最省心)
Android从API 1就提供了RoundRectShape类,专门用于创建圆角矩形形状,直接用它生成Drawable或者结合Canvas绘制就行——我在做低版本兼容项目时经常用这个方案,省心又靠谱,完全不用自己处理路径细节:
代码示例:
// 创建圆角矩形形状:第一个参数是四个角的半径(顺序:左上、右上、右下、左下),后面两个参数为null即可(分别对应内边距和内部圆角,按需设置) RoundRectShape roundRectShape = new RoundRectShape( new float[]{radius, radius, radius, radius, radius, radius, radius, radius}, null, null); // 生成ShapeDrawable并设置样式 ShapeDrawable drawable = new ShapeDrawable(roundRectShape); drawable.getPaint().setColor(Color.parseColor("#FF4081")); // 设置填充色 drawable.getPaint().setStrokeWidth(2); // 可选:设置边框宽度 drawable.getPaint().setStyle(Paint.Style.FILL_AND_STROKE); // 可选:填充加描边 // 绑定绘制区域并绘制 drawable.setBounds((int) left, (int) top, (int) right, (int) bottom); drawable.draw(canvas);
方案三:离屏缓冲结合Xfermode裁剪(适合复杂场景)
如果需要在圆角矩形上叠加半透明内容、渐变或者图片,Xfermode的方式会更灵活。核心思路是先在离屏Bitmap上绘制圆角遮罩,再将内容与遮罩合成,只保留遮罩区域的内容:
代码示例:
public void drawRoundRectWithContent(Canvas canvas, Paint paint, float left, float top, float right, float bottom, float radius, Bitmap contentBitmap) { // 创建与目标矩形等大的离屏缓冲Bitmap int width = (int) (right - left); int height = (int) (bottom - top); Bitmap offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas offscreenCanvas = new Canvas(offscreenBitmap); // 第一步:绘制圆角矩形遮罩 Paint maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); maskPaint.setColor(Color.WHITE); drawRoundRect(offscreenCanvas, maskPaint, 0, 0, width, height, radius); // 第二步:设置Xfermode,只保留遮罩与内容的交集区域 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // 第三步:绘制内容到离屏画布 offscreenCanvas.drawBitmap(contentBitmap, 0, 0, paint); // 第四步:将合成后的Bitmap绘制到原画布 canvas.drawBitmap(offscreenBitmap, left, top, null); // 重置Xfermode,避免影响后续绘制操作 paint.setXfermode(null); }
注意:使用离屏缓冲时要注意内存占用,避免频繁创建大尺寸Bitmap导致OOM。
内容的提问来源于stack exchange,提问作者A.G.




