圆形头像的最简单实现,直接粘贴代码就可以实现
2016-03-21 20:04
344 查看
public class CircleImageView extends ImageView {
/* 缩放的类型 */
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 1;
private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();// 位图画笔
private final Paint mBorderPaint = new Paint();// 边框画笔
private int mBorderColor = Color.BLACK;/* 默认边框颜色 */
private int mBorderWidth = 0;/* 默认边框宽度 */
private Bitmap mBitmap;/* 位图 */
private BitmapShader mBitmapShader;
private int mBitmapWidth; /* 位图宽度 */
private int mBitmapHeight;/* 位图高度 */
private float mDrawableRadius;/* 图片圆角 */
private float mBorderRadius; /* 边框圆角 */
private boolean mReady; /* 是否准备好 */
private boolean mSetupPending;/* 设置延时 */
/**
* 默认构造
*
* @param context
*/
public CircleImageView(Context context) {
super(context);
}
/**
* 自定义属性时,默认调用俩个参数的构造方法
*/
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
super.setScaleType(SCALE_TYPE);// 设置缩放的类型
/* 获取自定义属性 */
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CircleImageView, defStyle, 0);
/* 获取自定义属性 ---宽度 默认0 */
mBorderWidth = a.getDimensionPixelSize(
R.styleable.CircleImageView_border_width, 0);
/* 获取自定义属性 ---颜色 ,默认黑色 */
mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
Color.BLACK);
a.recycle();// 不释放,容易内存溢出
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
// @Override
// public ScaleType getScaleType() {
// return SCALE_TYPE;
// }
// @Override
// public void setScaleType(ScaleType scaleType) {
// if (scaleType != SCALE_TYPE) {
// throw new IllegalArgumentException(String.format(
// "ScaleType %s not supported.", scaleType));
// }
// }
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
/* 图片圆角 */
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
mBitmapPaint);
/* 边框圆角 */
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
mBorderPaint);
}
/*
* 当大小改变时,从新绘制
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
/*
* 设置图片
*/
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mBitmap = bm;
setup();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
setup();
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
/**
* @param drawable
* @return
*/
private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
public void setup() {
if (!mReady) {
mSetupPending = true;
return;
}
if (mBitmap == null) {
return;
}
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
/*位图画笔*/
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
/*边框画笔*/
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
/*位图的高度和匡度*/
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
/*边框*/
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
(mBorderRect.width() - mBorderWidth) / 2);
/*图片*/
mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
- mBorderWidth, mBorderRect.height() - mBorderWidth);
mDrawableRadius = Math.min(mDrawableRect.height() / 2,
mDrawableRect.width() / 2);
updateShaderMatrix();
invalidate();
}
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
* mBitmapHeight) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
(int) (dy + 0.5f) + mBorderWidth);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}
/* 缩放的类型 */
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 1;
private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
private final Paint mBitmapPaint = new Paint();// 位图画笔
private final Paint mBorderPaint = new Paint();// 边框画笔
private int mBorderColor = Color.BLACK;/* 默认边框颜色 */
private int mBorderWidth = 0;/* 默认边框宽度 */
private Bitmap mBitmap;/* 位图 */
private BitmapShader mBitmapShader;
private int mBitmapWidth; /* 位图宽度 */
private int mBitmapHeight;/* 位图高度 */
private float mDrawableRadius;/* 图片圆角 */
private float mBorderRadius; /* 边框圆角 */
private boolean mReady; /* 是否准备好 */
private boolean mSetupPending;/* 设置延时 */
/**
* 默认构造
*
* @param context
*/
public CircleImageView(Context context) {
super(context);
}
/**
* 自定义属性时,默认调用俩个参数的构造方法
*/
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
super.setScaleType(SCALE_TYPE);// 设置缩放的类型
/* 获取自定义属性 */
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CircleImageView, defStyle, 0);
/* 获取自定义属性 ---宽度 默认0 */
mBorderWidth = a.getDimensionPixelSize(
R.styleable.CircleImageView_border_width, 0);
/* 获取自定义属性 ---颜色 ,默认黑色 */
mBorderColor = a.getColor(R.styleable.CircleImageView_border_color,
Color.BLACK);
a.recycle();// 不释放,容易内存溢出
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
// @Override
// public ScaleType getScaleType() {
// return SCALE_TYPE;
// }
// @Override
// public void setScaleType(ScaleType scaleType) {
// if (scaleType != SCALE_TYPE) {
// throw new IllegalArgumentException(String.format(
// "ScaleType %s not supported.", scaleType));
// }
// }
@Override
protected void onDraw(Canvas canvas) {
if (getDrawable() == null) {
return;
}
/* 图片圆角 */
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius,
mBitmapPaint);
/* 边框圆角 */
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius,
mBorderPaint);
}
/*
* 当大小改变时,从新绘制
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
/*
* 设置图片
*/
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mBitmap = bm;
setup();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
setup();
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
/**
* @param drawable
* @return
*/
private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION,
COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
public void setup() {
if (!mReady) {
mSetupPending = true;
return;
}
if (mBitmap == null) {
return;
}
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
/*位图画笔*/
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setShader(mBitmapShader);
/*边框画笔*/
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
/*位图的高度和匡度*/
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
/*边框*/
mBorderRect.set(0, 0, getWidth(), getHeight());
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2,
(mBorderRect.width() - mBorderWidth) / 2);
/*图片*/
mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width()
- mBorderWidth, mBorderRect.height() - mBorderWidth);
mDrawableRadius = Math.min(mDrawableRect.height() / 2,
mDrawableRect.width() / 2);
updateShaderMatrix();
invalidate();
}
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width()
* mBitmapHeight) {
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
mShaderMatrix.setScale(scale, scale);
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth,
(int) (dy + 0.5f) + mBorderWidth);
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}
相关文章推荐
- java实现电话号码归属地的查询
- python中的map、filter、reduce函数
- 排序与查找之线性查找篇(C语言实现)
- win7(64位)下使用ltp(一):API调用
- Java异常处理和设计
- 冒泡排序与选择排序
- python学习笔记(第二章,快速入门)
- java语言程序设计第十版(Introduce to java) 课后习题 chapter6-25
- 2013 C#单元测试
- spring中的依赖注入和控制反转(二)——Spring 设值注入和构造注入比较
- java语言程序设计第十版(Introduce to java) 课后习题 chapter6-23
- 学习java心得 二
- java设置守护线程
- Java中合成和继承的区别
- java语言程序设计第十版(Introduce to java) 课后习题 chapter6-22
- Java自定义注解和元注解
- java语言程序设计第十版(Introduce to java) 课后习题 chapter6-18
- ubuntu下c++ stlport安装
- 自定义listview下拉刷新上拉加载更多以及与google官方的下拉刷新结合使用
- java语言程序设计第十版(Introduce to java) 课后习题 chapter6-17