有一个Path#addRoundRect()
的重载版本,它接受一个由八个float
值组成的数组,我们可以在其中为每个角指定x和y半径。这些值是以[x,y]对的形式给出的,从左上角开始,顺时针绕过其余的角。对于我们想要圆角的那些角,我们将一对值都设置为半径,对于我们不想要的角,则将它们保留为零。
作为一个说明性的例子,下面是一个简单的方法,它将返回一个Path
,可以在您的代码片段中使用:
private Path getPath(float radius, boolean topLeft, boolean topRight,
boolean bottomRight, boolean bottomLeft) {
final Path path = new Path();
final float[] radii = new float[8];
if (topLeft) {
radii[0] = radius;
radii[1] = radius;
}
if (topRight) {
radii[2] = radius;
radii[3] = radius;
}
if (bottomRight) {
radii[4] = radius;
radii[5] = radius;
}
if (bottomLeft) {
radii[6] = radius;
radii[7] = radius;
}
path.addRoundRect(new RectF(0, 0, getWidth(), getHeight()),
radii, Path.Direction.CW);
return path;
}
根据您提供的示例描述,需要将左上角和右上角进行四舍五入:
@Override
protected void onDraw(Canvas canvas) {
float radius = getContext().getResources().getDimension(R.dimen.round_corner_radius);
Path path = getPath(radius, true, true, false, false);
canvas.clipPath(path);
super.onDraw(canvas);
}
通常,我建议尽可能保持onDraw()
方法的精简,将任何不必要的内容移到其他地方。例如,半径的资源值可以在构造函数中检索并保存在字段中。此外,Path
只有在必要时才需要构建;即当View
的大小改变或半径或选择的角落发生变化时。
由于我编写了一个简单的自定义ImageView
来测试这个功能,因此我将在此处包含它,因为它演示了上述要点。此自定义View
还提供了XML属性,允许在布局中设置角落半径和圆角。
public class RoundishImageView extends ImageView {
public static final int CORNER_NONE = 0;
public static final int CORNER_TOP_LEFT = 1;
public static final int CORNER_TOP_RIGHT = 2;
public static final int CORNER_BOTTOM_RIGHT = 4;
public static final int CORNER_BOTTOM_LEFT = 8;
public static final int CORNER_ALL = 15;
private static final int[] CORNERS = {CORNER_TOP_LEFT,
CORNER_TOP_RIGHT,
CORNER_BOTTOM_RIGHT,
CORNER_BOTTOM_LEFT};
private final Path path = new Path();
private int cornerRadius;
private int roundedCorners;
public RoundishImageView(Context context) {
this(context, null);
}
public RoundishImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundishImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundishImageView);
cornerRadius = a.getDimensionPixelSize(R.styleable.RoundishImageView_cornerRadius, 0);
roundedCorners = a.getInt(R.styleable.RoundishImageView_roundedCorners, CORNER_NONE);
a.recycle();
}
public void setCornerRadius(int radius) {
if (cornerRadius != radius) {
cornerRadius = radius;
setPath();
invalidate();
}
}
public int getCornerRadius() {
return cornerRadius;
}
public void setRoundedCorners(int corners) {
if (roundedCorners != corners) {
roundedCorners = corners;
setPath();
invalidate();
}
}
public boolean isCornerRounded(int corner) {
return (roundedCorners & corner) == corner;
}
@Override
protected void onDraw(Canvas canvas) {
if (!path.isEmpty()) {
canvas.clipPath(path);
}
super.onDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setPath();
}
private void setPath() {
path.rewind();
if (cornerRadius >= 1f && roundedCorners != CORNER_NONE) {
final float[] radii = new float[8];
for (int i = 0; i < 4; i++) {
if (isCornerRounded(CORNERS[i])) {
radii[2 * i] = cornerRadius;
radii[2 * i + 1] = cornerRadius;
}
}
path.addRoundRect(new RectF(0, 0, getWidth(), getHeight()),
radii, Path.Direction.CW);
}
}
}
为使XML属性起作用,需要在您的
<resources>
中添加以下内容。您可以通过将此文件放入项目的
res/values/
文件夹中或将其添加到可能已经存在的文件中来实现这一点。
attrs.xml
<resources>
<declare-styleable name="RoundishImageView">
<attr name="cornerRadius" format="dimension" />
<attr name="roundedCorners">
<flag name="topLeft" value="1" />
<flag name="topRight" value="2" />
<flag name="bottomRight" value="4" />
<flag name="bottomLeft" value="8" />
<flag name="all" value="15" />
</attr>
</declare-styleable>
</resources>
cornerRadius
是一个尺寸属性,应该指定为dp
或px
值。 roundedCorners
是一个标志属性,可以使用竖线字符|
选择多个角落。例如:
<com.mycompany.myapp.RoundishImageView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/riv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="@drawable/magritte"
app:cornerRadius="@dimen/round_corner_radius"
app:roundedCorners="topLeft|topRight" />
![screenshot](https://istack.dev59.com/I0KU1.webp)
ImageView
的背景进行任何操作。 - Mike M.ColorDrawable
设置为图像,而不是设置背景。例如:imageView.setImageDrawable(new ColorDrawable(Color.BLUE))
。 - Mike M.