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