自定义圆形图片控件

圆形图片效果是项目中一个常用的功能,很多头像都是这种显示样式的。网上有很多成熟的控件,也有很多比较优秀的第三方图片框架可以实现该功能。但是这个功能是掌握自定义控件的一个很好的例子,所以就自己写了一个简单的控件来实现该效果,练习一下。本文要实现的功能就是将一张普通图片以圆形图片的形式显示出来,并添加边框。最终的效果如下图:

自定义圆形图片控件_第1张图片

实现步骤如下:

1、先自定义一个CircleImageView继承至AppCompatImageView,并重写相关构造方法,在构造方法中调用一个初始化方法,用来做一些初始化操作。

   public CircleImageView(Context context) {
        super(context);
        init(context, null);
    }

    public CircleImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

2、在初始化方法init中,初始化自定义的属性,边框画笔。

    //默认值
    private static final int DEFAULT_COLOR = Color.RED;
    private static final int DEFAULT_BORDER_WIDTH = 5;

    //边框颜色
    private int mBorderColor = DEFAULT_COLOR;

    //边框宽度
    private int mBorderWidth = DEFAULT_BORDER_WIDTH;

    //绘制圆形边框画笔
    private Paint mBorderPaint;

    /**
     * 初始化方法
     *
     * @param context 上下文
     * @param attrs   属性
     */
    private void init(Context context, AttributeSet attrs) {

        //初始化自定义属性
        if (attrs != null) {
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView);
            mBorderColor = array.getColor(R.styleable.CircleImageView_border_color, DEFAULT_COLOR);
            mBorderWidth = (int) array.getDimension(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
            array.recycle();
        }

        //初始化mBorderPaint
        mBorderPaint = new Paint();
        mBorderPaint.setAntiAlias(true);
        mBorderPaint.setColor(mBorderColor);
    }

3、重写控件的onMeasure方法,使其宽、高相等,并将该值声明为成员变量为全局所使用。

    //控件宽、高的尺寸
    private int mSize;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mSize = Math.min(getMeasuredHeight(), getMeasuredWidth());
        setMeasuredDimension(mSize, mSize);
    }

4、重写onDraw方法进行最终绘制,绘制分两部分,一个是边框的绘制,一个是圆形图片的绘制,圆形图片的绘制要先绘制圆然后在绘制图片,在取两者的交集。

    /**
     * 重写onDraw方法绘制圆形图
     *
     * @param canvas 画布
     */
    @Override
    protected void onDraw(Canvas canvas) {
        if (getDrawable() != null && getDrawable() instanceof BitmapDrawable) {
            //获取原始Bitmap
            Bitmap originalBitmap = ((BitmapDrawable) getDrawable()).getBitmap();

            //画边框圆
            canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mBorderPaint);

            //画圆形Bitmap
            canvas.drawBitmap(getCopyBitmap(originalBitmap), 0, 0, null);
        } else {
            super.onDraw(canvas);
        }
    }


    /**
     * 创建圆形Bitmap
     *
     * @param originalBitmap 原始Bitmap
     * @return 圆形Bitmap
     */
    private Bitmap getCopyBitmap(Bitmap originalBitmap) {

        //创建一个Bitmap副本
        Bitmap copyBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), originalBitmap.getConfig());

        //创建画板
        Canvas canvas = new Canvas(copyBitmap);

        //创建画笔
        Paint bitmapPaint = new Paint();
        bitmapPaint.setAntiAlias(true);

        //绘制圆形区域
        canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2 - 2 * mBorderWidth, bitmapPaint);

        //绘制Bitmap并和圆形区域取交集
        bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(originalBitmap, 0, 0, bitmapPaint);

        //返回最终的圆形Bitmap
        return copyBitmap;
    }

最终的完整代码:

package cn.znh.circleimageview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.BitmapDrawable;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

/**
 * 作者:zhaonh on 2018/7/23 21:51
 * 

* 自定义圆形图片展示控件 */ public class CircleImageView extends AppCompatImageView { //默认值 private static final int DEFAULT_COLOR = Color.RED; private static final int DEFAULT_BORDER_WIDTH = 5; //边框颜色 private int mBorderColor = DEFAULT_COLOR; //边框宽度 private int mBorderWidth = DEFAULT_BORDER_WIDTH; //绘制圆形边框画笔 private Paint mBorderPaint; //控件宽、高的尺寸 private int mSize; public CircleImageView(Context context) { super(context); init(context, null); } public CircleImageView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context, attrs); } public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } /** * 初始化方法 * * @param context 上下文 * @param attrs 属性 */ private void init(Context context, AttributeSet attrs) { //初始化自定义属性 if (attrs != null) { TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView); mBorderColor = array.getColor(R.styleable.CircleImageView_border_color, DEFAULT_COLOR); mBorderWidth = (int) array.getDimension(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); array.recycle(); } //初始化mBorderPaint mBorderPaint = new Paint(); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mBorderColor); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mSize = Math.min(getMeasuredHeight(), getMeasuredWidth()); setMeasuredDimension(mSize, mSize); } /** * 重写onDraw方法绘制圆形图 * * @param canvas 画布 */ @Override protected void onDraw(Canvas canvas) { if (getDrawable() != null && getDrawable() instanceof BitmapDrawable) { //获取原始Bitmap Bitmap originalBitmap = ((BitmapDrawable) getDrawable()).getBitmap(); //画边框圆 canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mBorderPaint); //画圆形Bitmap canvas.drawBitmap(getCopyBitmap(originalBitmap), 0, 0, null); } else { super.onDraw(canvas); } } /** * 创建圆形Bitmap * * @param originalBitmap 原始Bitmap * @return 圆形Bitmap */ private Bitmap getCopyBitmap(Bitmap originalBitmap) { //创建一个Bitmap副本 Bitmap copyBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), originalBitmap.getConfig()); //创建画板 Canvas canvas = new Canvas(copyBitmap); //创建画笔 Paint bitmapPaint = new Paint(); bitmapPaint.setAntiAlias(true); //绘制圆形区域 canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2 - 2 * mBorderWidth, bitmapPaint); //绘制Bitmap并和圆形区域取交集 bitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); canvas.drawBitmap(originalBitmap, 0, 0, bitmapPaint); //返回最终的圆形Bitmap return copyBitmap; } }

你可能感兴趣的:(Android)