Android实现圆角图片的简易版:
最初想写这个东西是看到github的圆角图片代码巨长,不好看而且不太实用,基本上很长的代码用到的部分不会很多的。核心代码其实就那么几行。
private Bitmap createCircleBitmap(Bitmap source, int min){
<span style="white-space:pre"> </span>final Paint paint = new Paint();
<span style="white-space:pre"> </span>paint.setAntiAlias(true);
<span style="white-space:pre"> </span>Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);
<span style="white-space:pre"> </span>//产生同样大小的画布
<span style="white-space:pre"> </span>Canvas canvas = new Canvas(target);
<span style="white-space:pre"> </span>//绘制圆形
<span style="white-space:pre"> </span>canvas.drawCircle(min / 2, min / 2, min / 2, paint);
<span style="white-space:pre"> </span>//设置模式
<span style="white-space:pre"> </span>paint.setXfermode(new PortDuffXfermode(PorterDuff.Mode.SRC_IN));
<span style="white-space:pre"> </span>//画bitmap<叠加模式,取src包含在target的部分>
<span style="white-space:pre"> </span>canvas.drawBitmap(source, 0, 0, paint);
<span style="white-space:pre"> </span>return target;
}
现在我来解释一下为什么这么简单就实现了图片的圆角,当然这只是核心代码,要是想实用起来方便需要更好地包装。其实主要是靠paint.setXfermode(new PorterDuff.Mode.SRC_IN);这一行代码,这种模式是两个绘制的效果取叠加部分,也就是说,我们第一个画的是一个圆形,第二个画的是一个bitmap<可能是方形>取二者重合的部分。是不是很简单,接下来介绍一下PorterDuff.Mode的详细实用方法和定义。
PorterDuff.Mode其实是PorterDuff类的一个枚举变量,这个类官方文档上也怎么介绍,只知道它直接继承自Object,而PorterDuff.Mode包含了十八种模式。具体的大家可以看看文档
/**
* 测试PorterDuff类的枚举变量
* */
@SuppressLint("NewApi") @SuppressWarnings("deprecation")
public void textPorterDuff(ImageView imageView, int min){
final Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
paint.setColor(Color.BLUE);
canvas.drawCircle(min / 4, min / 4, min / 4, paint);
paint.setColor(Color.RED);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
canvas.drawRect(min / 4, min / 4, min, min, paint);
imageView.setBackground(new BitmapDrawable(target));
}
最后结果如图所示,大家可以自行设置
下面开始粘贴源码
package vgod.library.circleimageview;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class CustomImageView extends View{
/**
* 种类,圆角或者圆形
* */
private int type;
private static final int TYPE_CIRCLE = 0;
private static final int TYPE_ROUND = 1;
/**
* Bitmap picture
* */
private Bitmap mSource;
/**
* radius
* */
private int mRadius;
/**
* 控件的高度
* */
private int mHeight;
/**
* 宽度
* */
private int mWidth;
public CustomImageView(Context context, AttributeSet attrs){
super(context, attrs);
}
public CustomImageView(Context context){
this(context,null);
}
/**
* 初始化自定义的参数
* */
public CustomImageView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.CustomImageView_src:
mSource = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
break;
case R.styleable.CustomImageView_type:
type = a.getInt(attr, 0);// 默认为Circle
case R.styleable.CustomImageView_borderRadius:
mRadius= a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10f,
getResources().getDisplayMetrics()));// 默认为10DP
default:
break;
}
}
a.recycle();
}
/**
* 计算控件的高度和宽度
* */
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
/**
* 设置宽度
* */
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {//match_parent , accurate
mWidth = specSize;
} else {
//由图片决定
int desireByImg = getPaddingLeft() + getPaddingRight() +mSource.getWidth();
if (specMode == MeasureSpec.AT_MOST) {//wrap_contect
mWidth = Math.min(desireByImg, specSize);
} else {//自己决定
mWidth = desireByImg;
}
}
/***
* 设置高度
*/
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match_parent , accurate
{
mHeight = specSize;
} else
{
int desire = getPaddingTop() + getPaddingBottom()
+ mSource.getHeight();
if (specMode == MeasureSpec.AT_MOST)// wrap_content
{
mHeight = Math.min(desire, specSize);
} else
mHeight = desire;
}
setMeasuredDimension(mWidth, mHeight);
}
@SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas){
switch (type) {
case TYPE_CIRCLE:
int min = Math.min(mWidth, mHeight);
/**
* 如果长度不一致,则按照小的压缩
* */
mSource = Bitmap.createScaledBitmap(mSource, min, min,false);
canvas.drawBitmap(createCircleBitmap(mSource, min), 0, 0, null);
break;
case TYPE_ROUND:
canvas.drawBitmap(createCornorBitmap(mSource), 0, 0, null);
break;
default:
break;
}
}
/**
* 绘制圆形图片
* */
public Bitmap createCircleBitmap(Bitmap source, int min){
final Paint paint = new Paint();
Bitmap target = Bitmap.createBitmap(min, min, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
paint.setAntiAlias(true);
canvas.drawCircle(min / 2, min / 2, min / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
/**
* 绘制圆角图片
* */
public Bitmap createCornorBitmap(Bitmap source){
final Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap target = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(target);
RectF rect = new RectF(0, 0, source.getWidth(), source.getHeight());
canvas.drawRoundRect(rect, mRadius, mRadius, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(source, 0, 0, paint);
return target;
}
}