Android ImageView 圆角实现
Android开发过程中,ImageView是必不可少的几种控件之一,通常为了美观,图标等内容会设置为圆角,以下简单总结了几种设置圆角的方法。
1. RoundedImageView
RoundImageView为第三方库,在build.gradle(:app)中使用以下语句导入:
implementation 'com.makeramen:roundedimageview:2.3.0'
该控件使用起来也非常方便,圆角设置为10dp示例如下:
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/iv_beauty"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:src="@drawable/beauty1"
app:riv_corner_radius_bottom_left="10dp"
app:riv_corner_radius_bottom_right="10dp"
app:riv_corner_radius_top_left="10dp"
app:riv_corner_radius_top_right="10dp" />
效果如下:
2. CardView
CardView为Android系统自带控件,使用CardView包裹ImageView也可以实现圆角效果,需要注意的是,CardView有可能会影响到控件层级,可以通过设置app:cardElevation="0dp"
避免该问题:
<androidx.cardview.widget.CardView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
app:cardCornerRadius="10dp"
app:cardElevation="0dp">
<ImageView
android:id="@+id/iv_beauty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/beauty1" />
</androidx.cardview.widget.CardView>
3. Glide
Glide是图片加载常用的控件,通过Glide亦能实现圆角效果,Glide引入:
implementation 'com.github.bumptech.glide:glide:4.13.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0'
代码如下:
RequestOptions options = new RequestOptions().transform(new RoundedCorners(ScreenUtil.dp2px(10)));
Glide.with(this).load(R.drawable.beauty2).apply(options).into(r.ivBeauty);
4. ViewOutlineProvider
通过自定义ViewOutlineProvider也可以实现圆角效果:
public class RoundViewOutlineProvider extends ViewOutlineProvider {
private final float radius;
public RoundViewOutlineProvider(float radius) {
this.radius = radius;
}
@Override
public void getOutline(View view, Outline outline) {
int leftMargin = 0;
int topMargin = 0;
Rect selfRect = new Rect(leftMargin, topMargin, view.getWidth(), view.getHeight());
outline.setRoundRect(selfRect, radius);
}
}
使用:
r.ivBeauty.setOutlineProvider(new RoundViewOutlineProvider(ScreenUtil.dp2px(10)));
r.ivBeauty.setClipToOutline(true);
5. 自定义view
对于圆角使用比较多的情况,其实最好的选择是让美术提供附带圆角的切件,可以最大限度避免额外的操作。但是,如果只有非圆角切件且使用地方较多,那么自定义view会是一个不错的选择。
自定义圆角的实现总体上有两种方式,第一种方式是对Bitmap进行操作,第二种方式是对画布进行操作,通过canvas.clipPath
完成对画布的裁剪,从而达到圆角的效果。
如果在xml中设置了背景颜色,则通过canvas.clipPath
不会生效,此时可以在自定义view种新增一字段,用于绘制背景,在代码中手动调用,自定义view代码如下:
public class RoundedImageView extends AppCompatImageView {
private Paint paint;
private Path clipPath;
private RectF rectF;
private int radius;
private int bgColor;
public RoundedImageView(Context context) {
this(context, null);
}
public RoundedImageView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
clipPath = new Path();
rectF = new RectF();
radius = 0;
bgColor = 0xFFFFFF;
}
public void setRadius(int radius) {
this.radius = radius;
invalidate();
}
public void setBgColor(int bgColor) {
this.bgColor = bgColor;
paint.setColor(bgColor);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
clipPath.reset();
rectF.set(0, 0, getWidth(), getHeight());
clipPath.addRoundRect(rectF, radius, radius, Path.Direction.CW);
// int save = canvas.save();
canvas.clipPath(clipPath);
canvas.drawRect(rectF, paint);
super.onDraw(canvas);
// canvas.restoreToCount(save);
}
}
6. 总结
以上简单列举了几种实现圆角的方式。
值得一提的是,如果xml中ImageView scaleType设置成了centerCrop,则上述Glide实现圆角的方式会失效,原因可能是xml scaleType字段加载和Glide应用圆角选项有冲突,感兴趣的读者可以自行研究一下。此时可以去除掉xml中的scaleType属性,通过Glide在实现centerCrop效果的同时达到圆角的目的:
RequestOptions options = new RequestOptions().transform(new CenterCrop());
Glide.with(context)
.asBitmap()
.load(beautyResId)
.apply(options)
.into(new BitmapImageViewTarget(r.ivBeauty) {
@Override
protected void setResource(Bitmap resource) {
super.setResource(resource);
RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(context.getResources(), resource);
roundedBitmapDrawable.setCornerRadius(ScreenUtil.dp2px(8));
r.ivBeauty.setImageDrawable(roundedBitmapDrawable);
}
});