要用Glide实现一个带边框的圆角矩形,并且还可以自定义哪些边角是圆角,像这样:

直接看代码
public class BorderRoundTransformation implements Transformation<Bitmap> {
/**
* 用一个整形表示哪些边角需要加圆角边框
* 例如:0b1000,表示左上角需要加圆角边框
* 0b1110 表示左上右上右下需要加圆角边框
* 0b0000表示不加圆形边框
*/
private BitmapPool mBitmapPool;
private int mRadius; //圆角半径
private int mMargin; //边距
private int mBorderWidth;//边框宽度
private int mBorderColor;//边框颜色
private int mCornerPos; //圆角位置
public BorderRoundTransformation(Context context, int radius, int margin, int mBorderWidth, int mBorderColor, int position) {
mBitmapPool = Glide.get(context).getBitmapPool();
mRadius = radius;
mMargin = margin;
this.mBorderColor = mBorderColor;
this.mBorderWidth = mBorderWidth;
this.mCornerPos = position;
}
@Override
public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) {
Bitmap source = resource.get();
int width = source.getWidth();
int height = source.getHeight();
Bitmap bitmap = mBitmapPool.get(width, height, Bitmap.Config.ARGB_8888);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);//新建一个空白的bitmap
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));//设置要绘制的图形
Paint borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//设置边框样式
borderPaint.setColor(mBorderColor);
borderPaint.setStyle(Paint.Style.STROKE);
borderPaint.setStrokeWidth(mBorderWidth);
drawRoundRect(canvas, paint, width, height, borderPaint);
return BitmapResource.obtain(bitmap, mBitmapPool);
}
private void drawRoundRect(Canvas canvas, Paint paint, float width, float height, Paint borderPaint) {
float right = width - mMargin;
float bottom = height - mMargin;
float halfBorder = mBorderWidth / 2;
Path path = new Path();
float[] pos = new float[8];
int shift = mCornerPos;
int index = 3;
while (index >= 0) {//设置四个边角的弧度半径
pos[2 * index + 1] = ((shift & 1) > 0) ? mRadius : 0;
pos[2 * index] = ((shift & 1) > 0) ? mRadius : 0;
shift = shift >> 1;
index--;
}
path.addRoundRect(new RectF(mMargin + halfBorder, mMargin + halfBorder, right - halfBorder, bottom - halfBorder),
pos
, Path.Direction.CW);
canvas.drawPath(path, paint);//绘制要加载的图形
canvas.drawPath(path, borderPaint);//绘制边框
}
@Override
public String getId() {
//这里一定要是设置一个独一无二的ID,要不然重用会导致第二次调用不起效果,最好加上相应的变量参数,保证唯一性
return "RoundedTransformation(radius=" + mRadius + ", margin=" + mMargin + ", mBorderWidth" + mBorderWidth + ", mBorderColor" + mBorderColor + "mCornerPos" + mCornerPos + ")";
}
}
基于Glide的Transformation变换已经有可以用的库的了,添加即可
compile 'jp.wasabeef:glide-transformations:2.0.1'
这个依赖库里面已经有圆角矩形变换的实现了,只是还没有加边框的圆角矩形变换,这里添加下。本来想着加边框只要在RoundedCornersTransformation这个类里面加个绘制边框的功能就行,但是进去一看,没想到其本身的绘制圆角过程有点复杂,举个例子,我们需要绘制一个左上角带圆角的矩形,其核心代码是这样的
private void drawTopLeftRoundRect(Canvas canvas, Paint paint, float right, float bottom) {
//先在左上角画一个一个圆形
canvas.drawRoundRect(new RectF((float)this.mMargin, (float)this.mMargin, (float)(this.mMargin + this.mDiameter), (float)(this.mMargin + this.mDiameter)), (float)this.mRadius, (float)this.mRadius, paint);
//画圆形水平半径下面的长方形区域
canvas.drawRect(new RectF((float)this.mMargin, (float)(this.mMargin + this.mRadius), (float)(this.mMargin + this.mRadius), bottom), paint);
//画圆形垂直半径右边的长方形
canvas.drawRect(new RectF((float)(this.mMargin + this.mRadius), (float)this.mMargin, right, bottom), paint);
}
这三行绘制其实就是一个拼接,为了显示出圆角,给ImageView加了个背景,如下




通过前三张图绘制拼接成了第四张图。就实现了圆角,不得不说,这样也行但是绘制的次数也太多了,那如果我要给这张图加个边框不得也的再加三次绘制,那不得一共六次,绘制次数太多,影响效率,而且RoundedCornersTransformation这个类里面的判断实在太多,果断放弃了。
其实我们要绘制的是一个封闭区域,只要展示这个闭合区域的内容就行,就想到了Path,这个类里面有大量图形的绘制路径。画一个圆角矩形的话, 调用addRoundRect方法即可。看一下我写的BorderRoundTransformation的核心思想:
1.定义一个整形变量用来记录要绘制的边角位置mCornerPos,可以用一个四位二进制表示,其含义如下图

0表示该位置不绘制圆角,1表示需要绘制,这样用一个整形就可以自由组合了,哪些地方需要绘制,直接传一个整形数据就行。
2.利用Path画一个圆角矩形
3.在圆角矩形外面绘制一个边框
这样就大功告成了,看一下核心代码
private void drawRoundRect(Canvas canvas, Paint paint, float width, float height, Paint borderPaint) {
float right = width - mMargin;
float bottom = height - mMargin;
float halfBorder = mBorderWidth / 2; //这里为什么要除以2,是因为paint绘制Stroke时,并不是绘制在从线的一边绘制相应的宽度,而是以这条线为中心,两边个绘制1/2的宽度
Path path = new Path();
float[] pos = new float[8]; //圆角的半径长度数组,
int shift = mCornerPos;//圆角位置参数
int index = 3;
while (index >= 0) {//设置四个边角的弧度半径
pos[2 * index + 1] = ((shift & 1) > 0) ? mRadius : 0;//判断最后一位是否是1,是的话赋值圆角半径
pos[2 * index] = ((shift & 1) > 0) ? mRadius : 0;
shift = shift >> 1;//位置参数右移,判断下一位
index--;
}
path.addRoundRect(new RectF(mMargin + halfBorder, mMargin + halfBorder, right - halfBorder, bottom - halfBorder),
pos
, Path.Direction.CW);//这里为什么要加半个宽度是为了保证绘制的边框能够与Imagview边界对齐
canvas.drawPath(path, paint);//绘制要加载的图形
canvas.drawPath(path, borderPaint);//绘制边框
}```
调用方式:
Glide.with(context)
.load(url)
.bitmapTransform(new Transformation[]{new CenterCrop(getBaseContext())
, new BorderRoundTransformation(getBaseContext(), 10, 0, 5, Color.RED,5)})
.dontAnimate()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.into(imageView);
本文介绍了如何使用Glide在Android中实现带边框的圆角矩形图片变换,详细讲解了通过Path类来简化原本复杂的绘制过程,避免多次绘制影响效率。通过定义一个整形变量mCornerPos来指定圆角位置,并实现边框的绘制,提供了一种高效的方法来定制图片的圆角和边框。
1292

被折叠的 条评论
为什么被折叠?



