| 注册
请输入搜索内容

热门搜索

Java Linux MySQL PHP JavaScript Hibernate jQuery Nginx
f663x
10年前发布

Android应用自定义圆角图片RoundImageView

Android开发中图片控件ImageView默认的样子是矩形,方方正正的。在我们实际的项目中,有时候这些方正的图片显得有些呆板,我们就需要其它样式的图片,比较圆形图片(The rounded picture), 常见的就是app中用户头像等。要得到圆形图片有很多方式,比如draw一个circle,也可以用切好的圆形图片做背景或者写一个xml实现圆角功能等 等。不过在项目中,如果我们有多个地方要把图片展示出圆形的,而且图片是从网络上取的,这种情况还一个个处理就麻烦了,我们可以定义个圆形图片组件 RoundImageView,然后在要用的地方把RoundImageView 当成ImageView一样使用就行了。我在最近做的项目中也用到了圆形图片,所以做个笔记,方便下次使用!

首先看我们定义的RoundImageView:


public class RoundImageView extends ImageView {  private int mBorderThickness = 0;  private Context mContext;  private int defaultColor = 0xFFFFFFFF;  // 如果只有其中一个有值,则只画一个圆形边框  private int mBorderOutsideColor = 0;  private int mBorderInsideColor = 0;  // 控件默认长、宽  private int defaultWidth = 0;  private int defaultHeight = 0;    public RoundImageView(Context context) {  super(context);  mContext = context;  }      public RoundImageView(Context context, AttributeSet attrs) {  super(context, attrs);  mContext = context;  setCustomAttributes(attrs);  }      public RoundImageView(Context context, AttributeSet attrs, int defStyle) {  super(context, attrs, defStyle);  mContext = context;  setCustomAttributes(attrs);  }      private void setCustomAttributes(AttributeSet attrs) {//这里要用到自定义属性  TypedArray a = mContext.obtainStyledAttributes(attrs,  R.styleable.RoundImageView);  mBorderThickness = a.getDimensionPixelSize(  R.styleable.RoundImageView_border_thickness, 0);  mBorderOutsideColor = a  .getColor(R.styleable.RoundImageView_border_outside_color,  defaultColor);  mBorderInsideColor = a.getColor(  R.styleable.RoundImageView_border_inside_color, defaultColor);  }      @Override  protected void onDraw(Canvas canvas) {  Drawable drawable = getDrawable();  if (drawable == null) {  return;  }      if (getWidth() == 0 || getHeight() == 0) {  return;  }    if (drawable.getClass() == NinePatchDrawable.class)  return;  Bitmap b = ((BitmapDrawable) drawable).getBitmap();  Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);  if (defaultWidth == 0) {  defaultWidth = getWidth();  }  if (defaultHeight == 0) {  defaultHeight = getHeight();  }    int radius = 0;  if (mBorderInsideColor != defaultColor  && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框  radius = (defaultWidth < defaultHeight ? defaultWidth  : defaultHeight) / 2 - 2 * mBorderThickness;  // 画内圆  drawCircleBorder(canvas, radius + mBorderThickness / 2,  mBorderInsideColor);  // 画外圆  drawCircleBorder(canvas, radius + mBorderThickness  + mBorderThickness / 2, mBorderOutsideColor);  } else if (mBorderInsideColor != defaultColor  && mBorderOutsideColor == defaultColor) {// 定义画一个边框  radius = (defaultWidth < defaultHeight ? defaultWidth  : defaultHeight) / 2 - mBorderThickness;  drawCircleBorder(canvas, radius + mBorderThickness / 2,  mBorderInsideColor);  } else if (mBorderInsideColor == defaultColor  && mBorderOutsideColor != defaultColor) {// 定义画一个边框  radius = (defaultWidth < defaultHeight ? defaultWidth  : defaultHeight) / 2 - mBorderThickness;  drawCircleBorder(canvas, radius + mBorderThickness / 2,  mBorderOutsideColor);  } else {// 没有边框  radius = (defaultWidth < defaultHeight ? defaultWidth  : defaultHeight) / 2;  }  Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius);  bitmap = null;  canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight  / 2 - radius, null);  }      /**  * 获取裁剪后的圆形图片  */  public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) {  Bitmap scaledSrcBmp;  int diameter = radius * 2;      // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片  int bmpWidth = bmp.getWidth();  int bmpHeight = bmp.getHeight();  int squareWidth = 0, squareHeight = 0;  int x = 0, y = 0;  Bitmap squareBitmap;  if (bmpHeight > bmpWidth) {// 高大于宽  squareWidth = squareHeight = bmpWidth;  x = 0;  y = (bmpHeight - bmpWidth) / 2;  // 截取正方形图片  squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth,  squareHeight);  } else if (bmpHeight < bmpWidth) {// 宽大于高  squareWidth = squareHeight = bmpHeight;  x = (bmpWidth - bmpHeight) / 2;  y = 0;  squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth,  squareHeight);  } else {  squareBitmap = bmp;  }      if (squareBitmap.getWidth() != diameter  || squareBitmap.getHeight() != diameter) {  scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter,  diameter, true);      } else {  scaledSrcBmp = squareBitmap;  }  Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(),  scaledSrcBmp.getHeight(), Config.ARGB_8888);  Canvas canvas = new Canvas(output);      Paint paint = new Paint();  Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(),  scaledSrcBmp.getHeight());      paint.setAntiAlias(true);  paint.setFilterBitmap(true);  paint.setDither(true);  canvas.drawARGB(0, 0, 0, 0);  canvas.drawCircle(scaledSrcBmp.getWidth() / 2,  scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2,  paint);  paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  canvas.drawBitmap(scaledSrcBmp, rect, rect, paint);  // bitmap回收(recycle导致在布局文件XML看不到效果)  // bmp.recycle();  // squareBitmap.recycle();  // scaledSrcBmp.recycle();  squareBitmap = null;  scaledSrcBmp = null;  return output;  }      /**  * 边缘画圆  */  private void drawCircleBorder(Canvas canvas, int radius, int color) {  Paint paint = new Paint();  /* 去锯齿 */  paint.setAntiAlias(true);  paint.setFilterBitmap(true);  paint.setDither(true);  paint.setColor(color);  /* 设置paint的 style 为STROKE:空心 */  paint.setStyle(Paint.Style.STROKE);  /* 设置paint的外框宽度 */  paint.setStrokeWidth(mBorderThickness);  canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint);  }  }


在res/values建一个attrs.xml文件,加入自定义属性字段

<?xml version="1.0" encoding="utf-8"?>  <resources>      <declare-styleable name="RoundImageView">          <attr name="border_thickness" format="dimension" />          <attr name="border_outside_color" format="color" />          <attr name="border_inside_color" format="color" />      </declare-styleable>    </resources>


最后就直接把这个RoundImageView看作ImageView在你需要用的地方用就可以了。