我找到了一个可以制作所有四个角都是圆形的矩形的函数,但我想只让顶部两个角是圆形的。我该怎么做?
canvas.drawRoundRect(new RectF(0, 100, 100, 300), 6, 6, paint);
我找到了一个可以制作所有四个角都是圆形的矩形的函数,但我想只让顶部两个角是圆形的。我该怎么做?
canvas.drawRoundRect(new RectF(0, 100, 100, 300), 6, 6, paint);
绘制实心边框的一种简单有效的方法是使用裁剪 - 矩形裁剪基本上是免费的,比编写自定义路径需要更少的代码。
如果我想要一个顶部左侧和右侧圆角为50像素的300x300矩形,则可以执行以下操作:
canvas.save();
canvas.clipRect(0, 0, 300, 300);
canvas.drawRoundRect(new RectF(0, 0, 300, 350), 50, 50, paint);
canvas.restore();
这种方法只适用于对2或3个相邻角进行舍入,因此比基于Path的方法更少配置性,但是使用圆角矩形更有效率,因为drawRoundRect()完全由硬件加速(即被细分为三角形),而drawPath()总是回退到软件渲染(以软件方式绘制路径位图,并将其上传到GPU缓存中)。
对于小量稀疏绘制来说,并不是重大的性能问题,但是如果您正在动画化路径,则软件绘制的成本可能会使帧时间更长,并增加丢帧的几率。路径掩码还会占用内存。
如果您确实想采用基于Path的方法,我建议使用GradientDrawable来简化代码行数(假设您不需要设置自定义着色器,例如绘制位图)。
mGradient.setBounds(0, 0, 300, 300);
mGradient.setCornerRadii(new int[] {50,50, 50,50, 0,0, 0,0});
通过GradientDrawable#setCornerRadii(),您可以将任何角设置为任何圆角半径,并在状态之间合理地进行动画处理。
Paint p = new Paint();
p.setColor(color);
float[] corners = new float[]{
15, 15, // Top, left in px
15, 15, // Top, right in px
15, 15, // Bottom, right in px
15, 15 // Bottom,left in px
};
final Path path = new Path();
path.addRoundRect(rect, corners, Path.Direction.CW);
// Draw
canvas.drawPath(path, p);
Path
以及quadTo
函数,可以在更低级别的API中使用。fun Canvas.drawRoundRectPath(
rectF: RectF,
radius: Float,
roundTopLeft: Boolean,
roundTopRight: Boolean,
roundBottomLeft: Boolean,
roundBottomRight: Boolean,
paint: Paint) {
val path = Path()
//Move path cursor to start point
if (roundBottomLeft) {
path.moveTo(rectF.left, rectF.bottom - radius)
} else {
path.moveTo(rectF.left, rectF.bottom)
}
// drawing line and rounding top left curve
if (roundTopLeft) {
path.lineTo(rectF.left, rectF.top + radius)
path.quadTo(rectF.left, rectF.top, rectF.left + radius, rectF.top)
} else {
path.lineTo(rectF.left, rectF.top)
}
// drawing line an rounding top right curve
if (roundTopRight) {
path.lineTo(rectF.right - radius, rectF.top)
path.quadTo(rectF.right, rectF.top, rectF.right, rectF.top + radius)
} else {
path.lineTo(rectF.right, rectF.top)
}
// drawing line an rounding bottom right curve
if (roundBottomRight) {
path.lineTo(rectF.right, rectF.bottom - radius)
path.quadTo(rectF.right, rectF.bottom, rectF.right - radius, rectF.bottom)
} else {
path.lineTo(rectF.right, rectF.bottom)
}
// drawing line an rounding bottom left curve
if (roundBottomLeft) {
path.lineTo(rectF.left + radius, rectF.bottom)
path.quadTo(rectF.left, rectF.bottom, rectF.left, rectF.bottom - radius)
} else {
path.lineTo(rectF.left, rectF.bottom)
}
path.close()
drawPath(path, paint)
}
RectF
,该对象包含我们要应用曲线的尺寸。Canvas
中的drawLine()
和drawArc()
函数逐个绘制该图形。使用PaintDrawable可能更好:
val topLeftRadius = 10
val topRightRadius = 10
val bottomLeftRadius = 0
val bottomRightRadius = 0
val rect = Rect(0, 0, 100, 100)
val paintDrawable = PaintDrawable(Color.RED)
val outter = floatArrayOf(topLeftRadius, topLeftRadius, topRightRadius, topRightRadius,
bottomLeftRadius, bottomLeftRadius, bottomRightRadius, bottomRightRadius)
paintDrawable.setCornerRadii(outter)
paintDrawable.bounds = rect
paintDrawable.draw(canvas)
使用左侧圆角绘制圆角矩形
private void drawRoundRect(float left, float top, float right, float bottom, Paint paint, Canvas canvas) {
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
path.lineTo(right, bottom);
path.lineTo(left + radius, bottom);
path.quadTo(left, bottom, left, bottom - radius);
path.lineTo(left, top + radius);
path.quadTo(left, top, left + radius, top);
canvas.drawPath(path, onlinePaint);
}