通过创建custom ImageView并使用以下方法覆盖onDraw方法,将使ImageView具有圆角。引用
@Override
protected void onDraw(Canvas canvas) {
float radius = getContext().getResources().getDimension(R.dimen.round_corner_radius);
Path path = new Path();
RectF rect = new RectF(0, 0, this.getWidth(), this.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
如何有选择地制作圆角而不是使所有四个圆角都变圆。例如,仅使左上角和右上角变圆并使底角保持完整。这是通过位图执行的solution。我正在寻找在此onDraw方法中执行此操作,并且仅使用Path和RectF。
最佳答案
有一个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" />