Android自定义圆角矩形ImageView,支持Glide加载图片及颜色填充

前言:

 之前用到圆角的情况大都是自定义一个shape背景drawable及用到v7包下的CardView包裹View实现圆角矩形效果,还有就是在用户圆形头像的时候需要使用到圆角矩形(圆形可以看做是特殊的圆角矩形),诸如Button,Editext,TextView的圆角矩形颜色背景可以用shape实现,但是ImageView Res圆角还没用到过,它就不能简单地设置一个圆角矩形shape作为背景了。这篇文章将介绍如何自定义一个ImageView实现image圆角矩形的效果及加上Glide和颜色填充的支持。效果如下:

Android自定义圆角矩形ImageView,支持Glide加载图片及颜色填充_第1张图片

  1. 第一张图片为用Glide加载的远程图片;
  2. 第二张为本地图片(drawable);
  3. 第三张则为颜色填充。

代码编写

1. 继承AppCompatImageView,初始化

google推荐继承AppCompatImageView实现自定义ImageView实现更好地兼容。

/**
* 默认的圆角大小,单位为dp
 */
private static final float DEFAULT_CORNER = 10;
private Paint mPaint;
private int mCorner;

public RoundRectImageView(Context context) {
    this(context,null);
}

public RoundRectImageView(Context context, AttributeSet attrs) {
    this(context, attrs,0);
}

public RoundRectImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    mPaint = new Paint();
    TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.RoundRectImageView);
    mCorner = (int) typedArray.getDimension(R.styleable.RoundRectImageView_corner, dp2px(context, DEFAULT_CORNER));
    typedArray.recycle();
}

这里自定义了一个属性corner:

<declare-styleable name="RoundRectImageView">
    <attr name="corner" format="dimension">attr>
declare-styleable>

2. 重写onDraw(),裁剪图片

/**
 * 绘制圆角矩形图片
 */
@Override
protected void onDraw(Canvas canvas) {
    Drawable drawable = getDrawable();
    if ( drawable != null ) {
        Bitmap bitmap = null;
        // Drawable转Bitmap
        if(drawable instanceof GlideBitmapDrawable) {
            bitmap = ((GlideBitmapDrawable)drawable).getBitmap();
        } else if(drawable instanceof ColorDrawable){
            bitmap = Bitmap.createBitmap(getWidth(),getHeight(),
                    Config.ARGB_8888);
            bitmap.eraseColor(((ColorDrawable) drawable).getColor());//填充颜色
        }else{
            bitmap = ((BitmapDrawable)drawable).getBitmap();
        }
        Bitmap roundBitmap = getRoundBitmap(bitmap, mCorner);
        final Rect rectSrc = new Rect(0, 0, roundBitmap.getWidth(), roundBitmap.getHeight());
        final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
        // 重置画笔,不然会留下黑色区域
        mPaint.reset();
        canvas.drawBitmap(roundBitmap, rectSrc, rectDest, mPaint);
    } else {
        super.onDraw(canvas);
    }
}

其中的原理是先通过Drawable拿到Bitmap,对Bitmap进行裁剪,然后重绘Bitmap实现圆角矩形的效果。其中裁剪方法为:

/**
 * 裁剪图片
 * @param bitmap
 * @param corner
 * @return Bitmap
 */
private Bitmap getRoundBitmap(Bitmap bitmap, int corner) {
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
            bitmap.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(output);
    final Rect rect = new Rect(getPaddingLeft(), getPaddingTop(), bitmap.getWidth()-getPaddingRight(), bitmap.getHeight()-getPaddingBottom());
    final RectF rectF = new RectF(rect);
    mPaint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    mPaint.setColor(Color.WHITE);
    canvas.drawRoundRect(rectF, corner, corner, mPaint);
    // 设置图像混合模式为SRC_IN,裁剪出我们的圆角Bitmap
    mPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, mPaint);
    return output;
}

其中裁剪原理是通过两个图像进行混合,这里为SRC_IN模式,即可裁剪出我们需要的圆角矩形图像。

完整代码如下:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;


/**
 * 自定义圆角矩形ImageView
 * Created by LT on 2018/5/13.
 */
public class RoundRectImageView extends AppCompatImageView {

    /**
     * 默认的圆角大小,单位为dp
     */
    private static final float DEFAULT_CORNER = 10;
    private Paint mPaint;
    private int mCorner;

    public RoundRectImageView(Context context) {
        this(context,null);
    }

    public RoundRectImageView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public RoundRectImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mPaint = new Paint();
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.RoundRectImageView);
        mCorner = (int) typedArray.getDimension(R.styleable.RoundRectImageView_corner, dp2px(context, DEFAULT_CORNER));
        typedArray.recycle();
    }

    /**
     * 绘制圆角矩形图片
     */
    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if ( drawable != null ) {
            Bitmap bitmap = null;
            // Drawable转Bitmap
            if(drawable instanceof GlideBitmapDrawable) {
                bitmap = ((GlideBitmapDrawable)drawable).getBitmap();
            } else if(drawable instanceof ColorDrawable){
                bitmap = Bitmap.createBitmap(getWidth(),getHeight(),
                        Config.ARGB_8888);
                bitmap.eraseColor(((ColorDrawable) drawable).getColor());//填充颜色
            }else{
                bitmap = ((BitmapDrawable)drawable).getBitmap();
            }
            Bitmap roundBitmap = getRoundBitmap(bitmap, mCorner);
            final Rect rectSrc = new Rect(0, 0, roundBitmap.getWidth(), roundBitmap.getHeight());
            final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
            // 重置画笔,不然会留下黑色区域
            mPaint.reset();
            canvas.drawBitmap(roundBitmap, rectSrc, rectDest, mPaint);
        } else {
            super.onDraw(canvas);
        }
    }

    /**
     * 裁剪图片
     * @param bitmap
     * @param corner
     * @return Bitmap
     */
    private Bitmap getRoundBitmap(Bitmap bitmap, int corner) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        final Rect rect = new Rect(getPaddingLeft(), getPaddingTop(), bitmap.getWidth()-getPaddingRight(), bitmap.getHeight()-getPaddingBottom());
        final RectF rectF = new RectF(rect);
        mPaint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        mPaint.setColor(Color.WHITE);
        canvas.drawRoundRect(rectF, corner, corner, mPaint);
        // 设置图像混合模式为SRC_IN,裁剪出我们的圆角Bitmap
        mPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, mPaint);
        return output;
    }

    /**
     * dp转 px.
     * @param value the value
     * @return the int
     */
    public static int dp2px(Context context, float value) {
        final float scale = context.getResources().getDisplayMetrics().densityDpi;
        return (int) (value * (scale / 160) + 0.5f);
    }
}

你可能感兴趣的:(Android进阶,Android进阶)