当前位置: 移动技术网 > 移动技术>移动开发>Android > Android实现动态圆环的图片头像控件

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

2019年07月24日  | 移动技术网移动技术  | 我要评论

先看效果图:

现在大部分的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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网