欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现动态圆环的图片头像控件

程序员文章站 2024-03-02 08:10:04
先看效果图: 现在大部分的app上难免会使用到圆形头像,所以今天我给大家分享一个单独使用的,并且周围带有圆环动画的花哨圆形头像控件,本控件是在圆形头像控件基础上实现的...

先看效果图:

Android实现动态圆环的图片头像控件

现在大部分的app上难免会使用到圆形头像,所以今天我给大家分享一个单独使用的,并且周围带有圆环动画的花哨圆形头像控件,本控件是在圆形头像控件基础上实现的,只是在其周围再画一些不同大小的圆而已,就可以实现如图的效果。

圆形头像的基本原理是将设置的资源文件转化成bitmap,然后通过bitmapshader类将bitmap成为paint的渲染器,然后在ondraw()中通过canvas.drawcircle(rx,ry,radius,paint);画布上画圆,而这个圆就是形成了圆形头像。

在xml中通过src设置的资源文件在imageview的setimagedrawable(drawable)方法中可以得到drawable类型的图像,然后再将drawable转成bitmap就可以了

public void setimagedrawable(drawable drawable) { 
  super.setimagedrawable(drawable); 
  mbitmap = getbitmapfromdrawable(drawable); 
  setup(); 
} 
private bitmap getbitmapfromdrawable(drawable drawable) { 
 
  if (drawable == null) { 
   return null; 
  } 
 
  if (drawable instanceof bitmapdrawable) { 
   //从bitmap中间裁剪出最大的正方形 
   bitmap bitmap = ((bitmapdrawable) drawable).getbitmap(); 
   return getmaxsquarecenter(bitmap); 
   //return ((bitmapdrawable) drawable).getbitmap(); 
  } 
 
  try { 
   bitmap bitmap; 
 
   if (drawable instanceof colordrawable) { 
    bitmap = bitmap.createbitmap(colordrawable_dimension, colordrawable_dimension, bitmap_config); 
   } else { 
    int min = math.min(drawable.getintrinsicwidth(), drawable.getintrinsicheight()); 
    bitmap = bitmap.createbitmap(min, min, bitmap_config); 
   } 
 
   canvas canvas = new canvas(bitmap); 
   int left,top,right,buttom; 
   int width = canvas.getwidth(); 
   int height = canvas.getheight(); 
   int abs = math.abs(width - height); 
   if(width <= height){ 
    left = 0; 
    top = (height - abs) / 2; 
    right = width; 
    buttom = height - top; 
   }else{ 
    left = (width - abs) / 2; 
    top = 0; 
    right = width - left; 
    buttom = height; 
   } 
   //drawable.setbounds(0, 0, canvas.getwidth(), canvas.getheight()); 
   drawable.setbounds(left, top, right, buttom); 
   drawable.draw(canvas); 
   return bitmap; 
  } catch (outofmemoryerror e) { 
   return null; 
  } 
 } 
/** 
  * 从bitmap中间裁剪出最大的正方形 
  * @param bitmap 
  * @return 
  */ 
 private bitmap getmaxsquarecenter(bitmap bitmap){ 
  int w = bitmap.getwidth(); // 得到图片的宽,高 
  int h = bitmap.getheight(); 
  int cropwidth = w >= h ? h : w;// 裁切后所取的正方形区域边长 
  return bitmap.createbitmap(bitmap, (w - cropwidth)/2 , (h - cropwidth)/2, cropwidth, cropwidth, null, false); 
 } 

获取到bitmap对象后就可以将bitmap缩小一倍后,在将其画在画布上,这样就有地方来画周围的圆环了。

private void updateshadermatrix() { 
  float scale; 
  float dx = 0; 
  float dy = 0; 
 
  mshadermatrix.set(null); 
 
  if (mbitmapwidth * mdrawablerect.height() > mdrawablerect.width() * mbitmapheight) { 
   scale = mdrawablerect.height() / (float) mbitmapheight / 2; //将图片缩放在正中间 缩小一倍 
   dx = (mdrawablerect.width() - mbitmapwidth * scale) * 0.5f; 
  } else { 
   scale = mdrawablerect.width() / (float) mbitmapwidth / 2; //将图片缩放在正中间 缩小一倍 
   dy = (mdrawablerect.height() - mbitmapheight * scale) * 0.5f; 
  } 
 
  mshadermatrix.setscale(scale , scale ); 
 //在x轴上平移mdrawableradius,就在正中间了 
  mshadermatrix.posttranslate((int) (dx + 0.5f) + mborderwidth + mdrawableradius, (int) (dy + 0.5f) + mborderwidth); 
 
  mbitmapshader.setlocalmatrix(mshadermatrix); 
 } 

下面就是画图片周围的圆环了,就是在图片的外围画两个圆,一个半径大点,颜色浅点,一个半径小点,颜色深点就可以了,然后通过handler通过延时操作,不断的改变两个圆的半径大小和颜色的深浅,重绘就可以了

 private float mchangerateborder;//记录外圆执行动画时半径变化率 
 private float mchangerateouter;//记录内圆执行动画时半径变化率 
 private float mchangerateinner;//记录图片边框执行动画时半径变化率 
 private float mchangerange;//变化范围,view半径的1/6 
//*******执行动画*******// 
 //外圆执行动画时半径变化率 
 private float mrateouter[] = { 
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.88f,0.85f,0.82f,0.76f,0.72f,0.68f,0.60f,0.54f,0.48f, 
   0.40f,0.33f,0.28f,0.20f}; 
 //内圆执行动画时半径变化率 
 private float mrateinner[] = { 
   -1,-1,-1,-1,-1, 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.88f,0.84f,0.80f,0.72f,0.67f,0.60f,0.54f,0.48f,-1f 
   ,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f}; 
 //图片边框执行动画时半径变化率 
 private float mrateborder[] = { 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.90f,0.84f,0.78f,0.72f,0.64f,0.58f,-1f,-1f,-1f 
   ,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f 
   ,-1f,-1f,-1f,-1f}; 
 
 private int mrateindex;//动画变化率的索引 

handler不断改变半径的变化率和画笔的颜色

/** 
  * 按住执行动画 
  */ 
 private handler mhandler = new handler(){ 
  @override 
  public void handlemessage(message msg) { 
   super.handlemessage(msg); 
   int index = mrateindex ++; 
   mchangerateborder = mrateborder[(index)% mrateborder.length]; 
   setpaintcorlor(mborderpaint,mchangerateborder,default_border_color); 
   setpaintalpha(mborderpaint,(index)% mrateborder.length,mrateborder); 
   mchangerateouter = mrateouter[(index) % mrateouter.length]; 
   setpaintcorlor(mouterpaint,mchangerateouter,mouterpaintcolor); 
   setpaintalpha(mouterpaint,(index) % mrateouter.length,mrateouter); 
   mchangerateinner = mrateinner[(index) % mrateinner.length]; 
   setpaintcorlor(minnerpaint,mchangerateinner,minnerpaintcolor); 
   setpaintalpha(minnerpaint,(index) % mrateinner.length,mrateinner); 
 
   //system.out.println("---------mchangerate:"+mchangerateborder); 
   invalidate(); 
   mhandler.removecallbacksandmessages(null); 
   mhandler.sendemptymessagedelayed(0,30); 
  } 
 }; 

每执行一次handlemessage()就会触发(invalidate())view重绘,ondraw中不断的重绘,只需改变每个circle的半径即可

@override 
 protected void ondraw(canvas canvas) { 
 
  if (getdrawable() == null) { 
   return; 
  } 
 
  //画动画的图形 
  canvas.drawcircle(getwidth() / 2,getheight() / 2,getchangeradiusouter(mouterradius),mouterpaint); 
  canvas.drawcircle(getwidth() / 2,getheight() / 2,getchangeradiusinner(minnerradius),minnerpaint); 
 
  canvas.drawcircle(getwidth() / 2, getheight() / 2, mdrawableradius, mbitmappaint); 
  canvas.drawcircle(getwidth() / 2, getheight() / 2, getchangeradiusborder(mborderradius), mborderpaint); 
 } 

根据handler中给的变化率来计算每个circle的半径

private float getchangeradiusborder(float radius){ 
 
  return mchangerateborder * mchangerange + radius; 
 
 } 
 private float getchangeradiusouter(float radius){ 
 
  return mchangerateouter * mchangerange + radius; 
 
 } 
 private float getchangeradiusinner(float radius){ 
 
  return mchangerateinner * mchangerange + radius; 
 
 } 

这样在不断的向handler发送消息时,也就会不断的触发重绘,不断改变外围圆的大小,形成上图所见的动画效果
如下四个方法,就是来控制圆环所展示的不同状态

/** 
  * 开始动画 
  */ 
 public void startanim(){ 
 //让外围的圆环动起来 
  mhandler.sendemptymessagedelayed(0,30); 
 
 } 
 /** 
  * 停止动画 
  */ 
 public void stopanim(){ 
 //停止外圆环的动画,展示默认的大小 
  mhandler.removecallbacksandmessages(null); 
  mchangerateborder = 0; 
  mchangerateouter = 0; 
  mchangerateinner = 0; 
 
  initanimcolor(); 
 
  enteranim(); 
 } 
 /** 
  * 进入动画 
  */ 
 public void enteranim(){ 
 //展示外圆环,显示默认大小 
  mhandlerenter.sendemptymessage(0); 
 } 
 
 /** 
  * 退出动画 
  */ 
 public void exitanim(){ 
 //隐藏外圆环 
  mhandlerexit.sendemptymessage(0); 
 } 

好了,动态头像到这基本就实现了,进入动画和退出动画的代码就不贴出来分析了,如果发现bug或者有任何意见欢迎留言。

完整源码 

import android.content.context; 
import android.graphics.bitmap; 
import android.graphics.bitmapshader; 
import android.graphics.canvas; 
import android.graphics.color; 
import android.graphics.matrix; 
import android.graphics.paint; 
import android.graphics.rectf; 
import android.graphics.shader; 
import android.graphics.drawable.bitmapdrawable; 
import android.graphics.drawable.colordrawable; 
import android.graphics.drawable.drawable; 
import android.os.handler; 
import android.os.message; 
import android.util.attributeset; 
import android.widget.imageview; 
 
/** 
 * created by cj_28 on 2016/10/15. 
 */ 
public class dynamicavatarview extends imageview { 
 
 private static final scaletype scale_type = scaletype.center_crop; 
 
 private static final int colordrawable_dimension = 1; 
 private static final bitmap.config bitmap_config = bitmap.config.argb_8888; 
 
 private bitmap mbitmap; 
 private bitmapshader mbitmapshader; 
 
 private final matrix mshadermatrix = new matrix(); 
 private final paint mbitmappaint = new paint(); 
 private final paint mborderpaint = new paint(); 
 private final paint mouterpaint = new paint(); 
 private final paint minnerpaint = new paint(); 
 
 private static final int default_border_width = 3; 
 private static final int default_border_color = color.white; 
 private static final int outer_paint_color = color.parsecolor("#55ffffff"); 
 private static final int inner_paint_color = color.parsecolor("#66ffffff"); 
 
 private int mbordercolor = default_border_color; 
 private int mborderwidth = default_border_width; 
 
 private int mouterpaintcolor = outer_paint_color; 
 private int minnerpaintcolor = inner_paint_color; 
 
 private int mbitmapwidth; 
 private int mbitmapheight; 
 
 private final rectf mdrawablerect = new rectf(); 
 private final rectf mborderrect = new rectf(); 
 
 private float mdrawableradius;//显示的图片 
 private float mborderradius;//..//显示的图片上的边框 
 private float mouterradius;//外层动画 
 private float minnerradius;//..//内层动画 
 
 private float mrealdrawableradius;//这是view没有被缩放之前的mdrawableradius的半径 
 private float mrealborderradius;//.. 
 
 private boolean mready; 
 private boolean msetuppending; 
 
 private float mchangerateborder;//记录外圆执行动画时半径变化率 
 private float mchangerateouter;//记录内圆执行动画时半径变化率 
 private float mchangerateinner;//记录图片边框执行动画时半径变化率 
 private float mchangerange;//变化范围,view半径的1/6 
 
 //*******执行动画*******// 
 //外圆执行动画时半径变化率 
 private float mrateouter[] = { 
   -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.88f,0.85f,0.82f,0.76f,0.72f,0.68f,0.60f,0.54f,0.48f, 
   0.40f,0.33f,0.28f,0.20f}; 
 //内圆执行动画时半径变化率 
 private float mrateinner[] = { 
   -1,-1,-1,-1,-1, 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.88f,0.84f,0.80f,0.72f,0.67f,0.60f,0.54f,0.48f,-1f 
   ,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f}; 
 //图片边框执行动画时半径变化率 
 private float mrateborder[] = { 
   0,0.1f,0.2f,0.3f,0.4f,0.5f,0.6f,0.7f,0.8f,0.9f,1.0f 
   ,0.92f,0.90f,0.84f,0.78f,0.72f,0.64f,0.58f,-1f,-1f,-1f 
   ,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f,-1f 
   ,-1f,-1f,-1f,-1f}; 
 
 //private int mcolor[] = {0x55ffffff,0x44ffffff,0x33ffffff,0x22ffffff,0x11ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff,0x00ffffff}; 
 private int mrateindex;//动画变化率的索引 
 
 //*******进入动画*******// 
 //外圆执行动画时半径变化率 
 private float mrateouterenter[] = { 
   -2,-2,//外圆要缩小2个mchangerange才会完全隐藏 
   -2,-2,-2,-2,-2, 
   -0.8f,-0.6f,-0.4f,-0.2f,-0.1f, 
   0,0.1f,0.2f,0.3f,0.4f,0.5f 
   ,0.44f,0.4f,0.35f,0.3f,0.25f 
   ,0.20f,0.15f,0.1f,0.0f}; 
 //内圆执行动画时半径变化率 
 private float mrateinnerenter[] = { 
   -1,-1,//外圆要缩小1个mchangerange才会完全隐藏 
   -0.8f,-0.6f,-0.4f,-0.2f,-0.1f, 
   0,0.1f,0.2f,0.3f,0.35f,0.4f 
   ,0.45f,0.5f,0.45f,0.4f,0.35f 
   ,0.3f,0.25f,0.2f,0.15f,0.1f 
   ,0.05f,0f,0f,0f}; 
 private int mrateindexenter;//进入动画变化率的索引 
 
 //*******退出动画*******// 
 //外圆执行动画时半径变化率 
 private float mrateouterexit[] = { 
 
   0.0f,-0.2f,-0.4f,-0.6f,-0.8f 
   ,-1f,-1.2f,-1.4f,-1.6f,-1.8f 
   ,-2f}; 
 //内圆执行动画时半径变化率 
 private float mrateinnerexit[] = { 
 
   0.0f,-0.1f,-0.2f,-0.3f,-0.4f 
   ,-0.5f,-0.6f,-0.7f,-0.8f,-0.9f 
   ,-1f}; 
 private int mrateindexexit;//进入动画变化率的索引 
 
 
 /** 
  * 按住执行动画 
  */ 
 private handler mhandler = new handler(){ 
  @override 
  public void handlemessage(message msg) { 
   super.handlemessage(msg); 
   int index = mrateindex ++; 
   mchangerateborder = mrateborder[(index)% mrateborder.length]; 
   setpaintcorlor(mborderpaint,mchangerateborder,default_border_color); 
   setpaintalpha(mborderpaint,(index)% mrateborder.length,mrateborder); 
   mchangerateouter = mrateouter[(index) % mrateouter.length]; 
   setpaintcorlor(mouterpaint,mchangerateouter,mouterpaintcolor); 
   setpaintalpha(mouterpaint,(index) % mrateouter.length,mrateouter); 
   mchangerateinner = mrateinner[(index) % mrateinner.length]; 
   setpaintcorlor(minnerpaint,mchangerateinner,minnerpaintcolor); 
   setpaintalpha(minnerpaint,(index) % mrateinner.length,mrateinner); 
 
   //system.out.println("---------mchangerate:"+mchangerateborder); 
   invalidate(); 
   mhandler.removecallbacksandmessages(null); 
   mhandler.sendemptymessagedelayed(0,30); 
  } 
 }; 
 
 private handler mhandlerenter = new handler(){ 
  @override 
  public void handlemessage(message msg) { 
   super.handlemessage(msg); 
   int index = mrateindexenter ++; 
   if(index >= mrateouterenter.length) { 
    mrateindexenter = 0; 
    mhandlerenter.removecallbacksandmessages(null); 
    return; 
   } 
 
   mchangerateouter = mrateouterenter[(index) % mrateouterenter.length]; 
 
   mchangerateinner = mrateinnerenter[(index) % mrateinnerenter.length]; 
 
   invalidate(); 
   mhandlerenter.removecallbacksandmessages(null); 
   mhandlerenter.sendemptymessagedelayed(0,20); 
  } 
 }; 
 
 private handler mhandlerexit = new handler(){ 
  @override 
  public void handlemessage(message msg) { 
   super.handlemessage(msg); 
   int index = mrateindexexit ++; 
   if(index >= mrateouterexit.length) { 
    mrateindexexit = 0; 
    mhandlerexit.removecallbacksandmessages(null); 
    return; 
   } 
 
   mchangerateouter = mrateouterexit[(index) % mrateouterexit.length]; 
 
   mchangerateinner = mrateinnerexit[(index) % mrateinnerexit.length]; 
 
   invalidate(); 
   mhandlerexit.removecallbacksandmessages(null); 
   mhandlerexit.sendemptymessagedelayed(0,20); 
  } 
 }; 
 
 /** 
  * 设置outer和inner的画笔颜色 
  * @param paint 
  * @param rate 
  * @param color 
  */ 
 private void setpaintcorlor(paint paint,float rate,int color){ 
  if(rate < 0){ 
   paint.setcolor(color.transparent); 
  }else{ 
   paint.setcolor(color); 
  } 
 } 
 
 /** 
  * 设置透明度 
  * @param paint 
  * @param index 
  * @param rate 
  */ 
 private void setpaintalpha(paint paint,int index,float[] rate){ 
  int pre = index -1; 
  if(pre >= 0 ){ 
   if(rate[pre] > rate[index] && rate[index] > 0){ 
    int color = paint.getcolor(); 
 
    int colortransparent = color & 0xff000000; 
    int colorvalue = color & 0x00ffffff; 
    colortransparent = colortransparent >>> 7; 
    paint.setcolor((int)(rate[index] * colortransparent) << 7 | colorvalue); 
 
   } 
  } 
 } 
 
 public dynamicavatarview(context context) { 
  this(context,null); 
 } 
 
 public dynamicavatarview(context context, attributeset attrs) { 
  this(context, attrs,0); 
 
 } 
 
 public dynamicavatarview(context context, attributeset attrs, int defstyleattr) { 
  super(context, attrs, defstyleattr); 
  super.setscaletype(scale_type); 
 
  //可以执行了 
  mready = true; 
 
  if (msetuppending) { 
   setup(); 
   msetuppending = false; 
  } 
 } 
 
 @override 
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { 
 
  int widthmode = measurespec.getmode(widthmeasurespec); 
  int widthsize = measurespec.getsize(widthmeasurespec); 
  int heightmode = measurespec.getmode(heightmeasurespec); 
  int heightsize = measurespec.getsize(heightmeasurespec); 
 
  int size = math.min(widthsize, heightsize); 
 
  super.onmeasure(measurespec.makemeasurespec(size,widthmode), measurespec.makemeasurespec(size,heightmode)); 
 } 
 
 @override 
 protected void onlayout(boolean changed, int left, int top, int right, int bottom) { 
 
  super.onlayout(changed, left, top, right, bottom); 
  enteranim(); 
 } 
 
 @override 
 protected void ondraw(canvas canvas) { 
 
  if (getdrawable() == null) { 
   return; 
  } 
 
  //画动画的图形 
  canvas.drawcircle(getwidth() / 2,getheight() / 2,getchangeradiusouter(mouterradius),mouterpaint); 
  canvas.drawcircle(getwidth() / 2,getheight() / 2,getchangeradiusinner(minnerradius),minnerpaint); 
 
  canvas.drawcircle(getwidth() / 2, getheight() / 2, mdrawableradius, mbitmappaint); 
  canvas.drawcircle(getwidth() / 2, getheight() / 2, getchangeradiusborder(mborderradius), mborderpaint); 
 } 
 
 private float getchangeradiusborder(float radius){ 
 
  return mchangerateborder * mchangerange + radius; 
 
 } 
 private float getchangeradiusouter(float radius){ 
 
  return mchangerateouter * mchangerange + radius; 
 
 } 
 private float getchangeradiusinner(float radius){ 
 
  return mchangerateinner * mchangerange + radius; 
 
 } 
 
 private void initanimcolor(){ 
  mouterpaint.setstyle(paint.style.fill); 
  mouterpaint.setantialias(true); 
  mouterpaint.setcolor(mouterpaintcolor); 
  minnerpaint.setstyle(paint.style.fill); 
  minnerpaint.setantialias(true); 
  minnerpaint.setcolor(minnerpaintcolor); 
  //图片边框(默认白色) 
  mborderpaint.setcolor(mbordercolor); 
 
  mouterradius = mrealborderradius / 6 * 5; 
  minnerradius = mrealborderradius / 6 * 4; 
  mchangerange = mrealborderradius / 6; 
  mrateindex = 0; 
 } 
 
 /** 
  * 开始动画 
  */ 
 public void startanim(){ 
  mhandler.sendemptymessagedelayed(0,30); 
 
 } 
 /** 
  * 停止动画 
  */ 
 public void stopanim(){ 
  mhandler.removecallbacksandmessages(null); 
  mchangerateborder = 0; 
  mchangerateouter = 0; 
  mchangerateinner = 0; 
//  mborderpaint.setcolor(default_border_color); 
//  mouterpaint.setcolor(mouterpaintcolor); 
//  minnerpaint.setcolor(minnerpaintcolor); 
//  mrateindex = 0; 
  initanimcolor(); 
 
  //invalidate(); 
  enteranim(); 
 } 
 /** 
  * 进入动画 
  */ 
 public void enteranim(){ 
  mhandlerenter.sendemptymessage(0); 
 } 
 
 /** 
  * 退出动画 
  */ 
 public void exitanim(){ 
  mhandlerexit.sendemptymessage(0); 
 } 
 
 /** 
  * 设置外圆动画的颜色 
  * @param outerpaintcolor 
  */ 
 public void setouterpaintcolor(int outerpaintcolor) { 
  if (outerpaintcolor == mouterpaintcolor) { 
   return; 
  } 
  mouterpaintcolor = outerpaintcolor; 
  mouterpaint.setcolor(mouterpaintcolor); 
  invalidate(); 
 } 
 
 /** 
  * 设置内圆动画的颜色 
  * @param innerpaintcolor 
  */ 
 public void setinnerpaintcolor(int innerpaintcolor) { 
  if (innerpaintcolor == minnerpaintcolor) { 
   return; 
  } 
  minnerpaintcolor = innerpaintcolor; 
  minnerpaint.setcolor(minnerpaintcolor); 
  invalidate(); 
 } 
 
 /** 
  * 设置图片边框的颜色 
  * @param bordercolor 
  */ 
 public void setbordercolor(int bordercolor) { 
  if (bordercolor == mbordercolor) { 
   return; 
  } 
 
  mbordercolor = bordercolor; 
  mborderpaint.setcolor(mbordercolor); 
  invalidate(); 
 } 
 
 /** 
  * 设置图片边框的宽度 
  * @param borderwidth 
  */ 
 public void setborderwidth(int borderwidth) { 
  if (borderwidth == mborderwidth) { 
   return; 
  } 
 
  mborderwidth = borderwidth; 
  setup(); 
 } 
 
 @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 onsizechanged(int w, int h, int oldw, int oldh) { 
  super.onsizechanged(w, h, oldw, oldh); 
  //只有在此方法中调用setup,setup中的getwidth方法得到的值才不会是0, 
  setup(); 
 } 
 
 @override 
 public void setimagebitmap(bitmap bm) { 
  super.setimagebitmap(bm); 
  mbitmap = getmaxsquarecenter(bm); 
  setup(); 
 } 
 
 /** 
  * mxl中设置src就会走此方法 
  * @param drawable 
  */ 
 @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(); 
 } 
 
 /** 
  * 从bitmap中间裁剪出最大的正方形 
  * @param bitmap 
  * @return 
  */ 
 private bitmap getmaxsquarecenter(bitmap bitmap){ 
  int w = bitmap.getwidth(); // 得到图片的宽,高 
  int h = bitmap.getheight(); 
  int cropwidth = w >= h ? h : w;// 裁切后所取的正方形区域边长 
  return bitmap.createbitmap(bitmap, (w - cropwidth)/2 , (h - cropwidth)/2, cropwidth, cropwidth, null, false); 
 } 
 
 private bitmap getbitmapfromdrawable(drawable drawable) { 
 
  if (drawable == null) { 
   return null; 
  } 
 
  if (drawable instanceof bitmapdrawable) { 
   //从bitmap中间裁剪出最大的正方形 
   bitmap bitmap = ((bitmapdrawable) drawable).getbitmap(); 
   return getmaxsquarecenter(bitmap); 
   //return ((bitmapdrawable) drawable).getbitmap(); 
  } 
 
  try { 
   bitmap bitmap; 
 
   if (drawable instanceof colordrawable) { 
    bitmap = bitmap.createbitmap(colordrawable_dimension, colordrawable_dimension, bitmap_config); 
   } else { 
    int min = math.min(drawable.getintrinsicwidth(), drawable.getintrinsicheight()); 
    bitmap = bitmap.createbitmap(min, min, bitmap_config); 
   } 
 
   canvas canvas = new canvas(bitmap); 
   int left,top,right,buttom; 
   int width = canvas.getwidth(); 
   int height = canvas.getheight(); 
   int abs = math.abs(width - height); 
   if(width <= height){ 
    left = 0; 
    top = (height - abs) / 2; 
    right = width; 
    buttom = height - top; 
   }else{ 
    left = (width - abs) / 2; 
    top = 0; 
    right = width - left; 
    buttom = height; 
   } 
   //drawable.setbounds(0, 0, canvas.getwidth(), canvas.getheight()); 
   drawable.setbounds(left, top, right, buttom); 
   drawable.draw(canvas); 
   return bitmap; 
  } catch (outofmemoryerror e) { 
   return null; 
  } 
 } 
 
 private 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) / 2; 
  mrealborderradius = 2 * mborderradius; 
  //图片显示的范围 
  mdrawablerect.set(mborderwidth, mborderwidth, mborderrect.width() - mborderwidth, mborderrect.height() - mborderwidth); 
  //让图片显示的范围是控件大小的一半 
  mdrawableradius = math.min(mdrawablerect.height() / 2, mdrawablerect.width() / 2) / 2; 
  mrealdrawableradius = 2 * mdrawableradius; 
 
  updateshadermatrix(); 
  initanimcolor(); 
  invalidate(); 
 } 
 
 private void updateshadermatrix() { 
  float scale; 
  float dx = 0; 
  float dy = 0; 
 
  mshadermatrix.set(null); 
 
  if (mbitmapwidth * mdrawablerect.height() > mdrawablerect.width() * mbitmapheight) { 
   scale = mdrawablerect.height() / (float) mbitmapheight / 2; //将图片缩放在正中间 
   dx = (mdrawablerect.width() - mbitmapwidth * scale) * 0.5f; 
  } else { 
   scale = mdrawablerect.width() / (float) mbitmapwidth / 2; 
   dy = (mdrawablerect.height() - mbitmapheight * scale) * 0.5f; 
  } 
 
  mshadermatrix.setscale(scale , scale ); 
  mshadermatrix.posttranslate((int) (dx + 0.5f) + mborderwidth + mdrawableradius, (int) (dy + 0.5f) + mborderwidth); 
 
  mbitmapshader.setlocalmatrix(mshadermatrix); 
 } 
 
} 

参考:https://github.com/hdodenhof/circleimageview

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。