圆形Imagview有几种方法,这里我列举两种方法出来仅供大家参考,当然还有其它的几种方法,我就不一一赘述了
1.重写onDraw(Canvas canvas)通过Canvas来画圆,传入带bitmapShaper的画笔
public class CircleImageView extends ImageView {
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
//创建画笔
paint = new Paint();
paint.setAntiAlias(true); // 防止边缘的锯齿
paint.setColor(Color.WHITE); // 这里的颜色决定了边缘的颜色
mShaderMatrix=new Matrix();
}
/**
* 位图对象
* */
private Bitmap mbitmap;
Paint paint;
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
if(mbitmap==null){
mbitmap=DrawableToBitmap(drawable);
setBitmapsharder();
}
if(mbitmap==null)
return;
int radius=getWidth()> getHeight()?getHeight()/2:getWidth()/2;
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, paint);
}
BitmapShader mBitmapShader=null;
private void setBitmapsharder(){
if (mbitmap!=null&&paint!=null&&width!=0&&height!=0){
mBitmapShader=new BitmapShader(mbitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
paint.setShader(mBitmapShader);
float scale=0;
mBitmapHeight = mbitmap.getHeight();
mBitmapWidth = mbitmap.getWidth();
mShaderMatrix.set(null);
if (width>height) {
if(mBitmapWidth>mBitmapHeight)
scale=((float)height)/mBitmapHeight;
else
scale=((float)height)/mBitmapWidth;
} else {
if(mBitmapWidth>mBitmapHeight)
scale=((float)width)/mBitmapHeight;
else
scale=((float)width)/mBitmapWidth;
}
//设置图片缩放
mShaderMatrix.setScale(scale, scale);
//设置图片平移显示
if(mBitmapWidth>mBitmapHeight){
mShaderMatrix.postTranslate(-(mBitmapWidth-mBitmapHeight)*scale/2,0);
}else{
mShaderMatrix.postTranslate(0,-(mBitmapHeight-mBitmapWidth)*scale/2);
}
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}
Matrix mShaderMatrix;
private int mBitmapWidth;
private int mBitmapHeight;
private int height;
private int width;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
height=getHeight();
width=getWidth();
setBitmapsharder();
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mbitmap=bm;
setBitmapsharder();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mbitmap=DrawableToBitmap(drawable);
setBitmapsharder();
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mbitmap=DrawableToBitmap(getContext(),resId);
setBitmapsharder();
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
mbitmap=DrawableToBitmap(getDrawable());
setBitmapsharder();
}
/**
* Drawable转换为Bitmap
* */
public static Bitmap DrawableToBitmap(Drawable drawable){
if(drawable==null)
return null;
if(drawable instanceof BitmapDrawable)
return ((BitmapDrawable)drawable).getBitmap();
Bitmap bitmap=null;
//如果是ColorDrawable随便给一个宽高
if(drawable instanceof ColorDrawable)
bitmap=Bitmap.createBitmap(2,2,Bitmap.Config.ARGB_8888);
else
bitmap=Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(bitmap);
//设置绘制的矩形区域
drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* Drawable转换为Bitmap
* */
public static Bitmap DrawableToBitmap(Context mContext,int ResId){
Bitmap bitmap= BitmapFactory.decodeResource(mContext.getResources(),ResId);
return bitmap;
}
}
这里的有几个核心的点有
第一个就是ondraw里面画圆,注意圆心的坐标以及圆的半径(半径为最小)
第二点通过setBitmapSharder方法,里面t通过Martix设置位图的缩放比例以及位图的偏移量
关于Martix的操作
Matrix的操作,总共分为translate(平移),rotate(旋转),scale(缩放)和skew(倾斜)四种,每一种变换在 Android的API里都提供了set, post和pre三种操作方式,除了translate,其他三种操作都可以指定中心点。
set是直接设置Matrix的值,每次set一次,整个Matrix的数组都会变掉。
post是后乘,当前的矩阵乘以参数给出的矩阵。可以连续多次使用post,来完成所需的整个变换。
具体怎么用的可以去参考一下片文章Android Matrix详解
2.通过绘制圆形的Bitmap,绘制Imagvivew
public class CircleImageView extends ImageView {
public CircleImageView(Context context) {
super(context);
init();
}
public CircleImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
mScaleType=getScaleType();
//创建画笔
paint = new Paint();
paint.setAntiAlias(true); // 防止边缘的锯齿
paint.setColor(Color.BLACK); // 这里的颜色决定了边缘的颜色
}
/**
* 位图对象
* */
private Bitmap mbitmap;
Paint paint;
private Rect rect=new Rect();
ScaleType mScaleType;
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
if(mbitmap==null){
mbitmap=DrawableToBitmap(drawable);
}
if(mbitmap==null)
return;
int radius=getWidth()> getHeight()?getHeight()/2:getWidth()/2;
canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius, paint);
//把圆形bitmap居中对齐
canvas.drawBitmap(drawCircleBitmap(mbitmap, radius), getWidth() / 2-radius,getHeight() / 2-radius, paint);
}
/*
*画圆形的bitmap
*
*/
public static Bitmap drawCircleBitmap(Bitmap bmp, int radius){
if (bmp.getWidth() != radius || bmp.getHeight() != radius){
/**
* 把图片进行缩放,以宽高最小的一方为准,缩放图片比例
* */
double diameter=radius*2;//获取直径
if(bmp.getWidth()> bmp.getHeight()){
bmp = Bitmap.createScaledBitmap(bmp, (int)( diameter*bmp.getWidth()/bmp.getHeight()), (int)diameter, false);
}else if(bmp.getWidth()< bmp.getHeight()){
bmp = Bitmap.createScaledBitmap(bmp, (int)(diameter/bmp.getWidth()*bmp.getHeight()), (int) diameter, false);
}else{
bmp = Bitmap.createScaledBitmap(bmp, (int)diameter, (int)diameter, false);
}
}
Bitmap output = Bitmap.createBitmap(radius*2, radius*2, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
//设置画笔全透明
canvas.drawARGB(0, 0, 0, 0);
Paint paints = new Paint();
paints.setColor(Color.WHITE);
paints.setAntiAlias(true);//去锯齿
paints.setFilterBitmap(true);
//防抖动
paints.setDither(true);
//把图片圆形绘制在面部中心
canvas.drawCircle(radius, radius, radius, paints);
// 取两层绘制交集。显示前景色。
paints.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
Rect rect=new Rect();
if(bmp.getWidth()>=bmp.getHeight()){
rect.set(bmp.getWidth()/2-radius,0,bmp.getWidth()/2+radius,radius*2);
}else{
rect.set(0,bmp.getHeight()/2-radius,radius*2,bmp.getHeight()/2+radius);
}
Rect rect2=new Rect(0,0,radius*2,radius*2);
//第一个rect 针对bmp的绘制区域,rect2表示绘制到上面位置
canvas.drawBitmap(bmp, rect, rect2, paints);
bmp.recycle();
return output;
}
/**
* 设置显示类型
* */
@Override
public void setScaleType(ScaleType scaleType) {
super.setScaleType(scaleType);
mScaleType=scaleType;
}
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mbitmap=bm;
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mbitmap=DrawableToBitmap(drawable);
}
@Override
public void setImageResource(int resId) {
super.setImageResource(resId);
mbitmap=DrawableToBitmap(getContext(),resId);
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
mbitmap=DrawableToBitmap(getDrawable());
}
/**
* Drawable转换为Bitmap
* */
public static Bitmap DrawableToBitmap(Drawable drawable){
if(drawable==null)
return null;
if(drawable instanceof BitmapDrawable)
return ((BitmapDrawable)drawable).getBitmap();
Bitmap bitmap=null;
//如果是ColorDrawable随便给一个宽高
if(drawable instanceof ColorDrawable)
bitmap=Bitmap.createBitmap(2,2,Bitmap.Config.ARGB_8888);
else
bitmap=Bitmap.createBitmap(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight(),Bitmap.Config.ARGB_8888);
Canvas canvas=new Canvas(bitmap);
//设置绘制的矩形区域
drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
drawable.draw(canvas);
return bitmap;
}
/**
* Drawable转换为Bitmap
* */
public static Bitmap DrawableToBitmap(Context mContext,int ResId){
Bitmap bitmap= BitmapFactory.decodeResource(mContext.getResources(),ResId);
return bitmap;
}
}
这个中绘制方法更简单我觉得可以不用重新Imagview就可以实现,把 drawCircleBitmap方法就行封装一下得到圆形的bitmap然后在设置给Imageveiw就可以实现了绘制好之后记得把之前的的bitmap给reclye了
这里画圆形view使用是在画布上面画一个圆,然后把bitmap也画上去,然后去交叉前景图
具体paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN))
这里面的几种交叉取景可以参考Android Paint之 setXfermode PorterDuffXfermode 讲解这篇文字
3.还要其他的几种方式,比如画一个中间透明的圆形遮盖在上面等等