Glide带边框的圆角矩形变换

本文介绍了如何使用Glide在Android中实现带边框的圆角矩形图片变换,详细讲解了通过Path类来简化原本复杂的绘制过程,避免多次绘制影响效率。通过定义一个整形变量mCornerPos来指定圆角位置,并实现边框的绘制,提供了一种高效的方法来定制图片的圆角和边框。

要用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);







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值