dependencies {
compile 'de.hdodenhof:circleimageview:2.1.0'
}
然后看一下自定义属性attrs:
我们来分析一下setup()方法,该方法是CircleImageView的核心。
private void setup() {
// mReady和mSetupPending属性,在构造方法和setup()方法都有引用和赋值
// 目的是确保setup()内部逻辑的执行是在构造方法执行完毕之后,即获取到自定义属性参数之后
if (!mReady) {
mSetupPending = true;
return;
}
// 图片宽高为0,不往下执行
if (getWidth() == 0 && getHeight() == 0) {
return;
}
// 只有传入了图片,才会往下执行
if (mBitmap == null) {
invalidate();
return;
}
// BitmapShader类用来渲染头像
// 参数1:要处理的bitmap对象,参数2和3:指定模式为对图片的边缘进行拉伸
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);
// 底色画笔:设置样式为填充
mFillPaint.setStyle(Paint.Style.FILL);
// 底色画笔:设置抗锯齿
mFillPaint.setAntiAlias(true);
// 底色画笔:设置颜色
mFillPaint.setColor(mFillColor);
// 获取原图的高度
mBitmapHeight = mBitmap.getHeight();
// 获取原图的宽度
mBitmapWidth = mBitmap.getWidth();
// 设置边框的显示区域
mBorderRect.set(calculateBounds());
// 计算边框的半径
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
// 设置图片的显示区域为上面计算出来的mBorderRect
mDrawableRect.set(mBorderRect);
// 如果边框不是覆盖在图片之上,并且边框宽度大于0,扩大图片的显示区域,增加mBorderWidth-1
if (!mBorderOverlay && mBorderWidth > 0) {
mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
}
// 计算图片的半径
mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
// 该方法内部只有一行代码,mBitmapPaint.setColorFilter(mColorFilter),给bitmap添加滤镜
applyColorFilter();
updateShaderMatrix();// 下文会介绍
invalidate();// 下文会介绍
}
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
// 这里取最小的缩放比例,以尽量保证图片的质量
// 判断如果宽度的比例大于高度的比例,取高度的缩放比,平移x轴方向
// 否则取宽度的缩放比,平移y轴方向
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:缩放
mShaderMatrix.setScale(scale, scale);
// 设置mShaderMatrix:平移
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
// 将mShaderMatrix设置到mBitmapShader
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
在setup()方法中最后一行执行invalidate(),触发View的onDraw()方法。
@Override
protected void onDraw(Canvas canvas) {
// 如果禁止显示圆形(setDisableCircularTransformation()方法可设置),则不往下执行。
if (mDisableCircularTransformation) {
super.onDraw(canvas);
return;
}
// 未设置图片,不往下执行
if (mBitmap == null) {
return;
}
// 如果底色不是透明,绘制底色
if (mFillColor != Color.TRANSPARENT) {
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);
}
// 使用上面设置好的mDrawableRect、mDrawableRadius、mBitmapPaint,绘制圆形图片,即内圆
canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);
// 如果边框宽度大于0,使用上面设置好的mBorderRect、mBorderRadius、mBorderPaint,绘制圆形边框,即外圆
if (mBorderWidth > 0) {
canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
}
}