1 package com.archive.xunji.widgets; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.*; 6 import android.graphics.drawable.BitmapDrawable; 7 import android.graphics.drawable.Drawable; 8 import android.graphics.drawable.NinePatchDrawable; 9 import android.util.AttributeSet; 10 import android.widget.ImageView; 11 import com.archive.xunji.R; 12 import com.lidroid.xutils.bitmap.core.AsyncDrawable; 13 14 /** 15 * 圆形ImageView,可设置最多两个宽度不同且颜色不同的圆形边框。 16 * 17 * 18 */ 19 public class RoundImageView extends ImageView { 20 private int mBorderThickness = 0; 21 private Context mContext; 22 private int defaultColor = 0xFFFFFFFF; 23 // 如果只有其中一个有值,则只画一个圆形边框 24 private int mBorderOutsideColor = 0; 25 private int mBorderInsideColor = 0; 26 // 控件默认长、宽 27 private int defaultWidth = 0; 28 private int defaultHeight = 0; 29 30 public RoundImageView(Context context) { 31 super(context); 32 mContext = context; 33 } 34 35 public RoundImageView(Context context, AttributeSet attrs) { 36 super(context, attrs); 37 mContext = context; 38 setCustomAttributes(attrs); 39 } 40 41 public RoundImageView(Context context, AttributeSet attrs, int defStyle) { 42 super(context, attrs, defStyle); 43 mContext = context; 44 setCustomAttributes(attrs); 45 } 46 47 private void setCustomAttributes(AttributeSet attrs) { 48 TypedArray a = mContext.obtainStyledAttributes(attrs, 49 R.styleable.roundedimageview); 50 mBorderThickness = a.getDimensionPixelSize( 51 R.styleable.roundedimageview_border_thickness, 0); 52 mBorderOutsideColor = a 53 .getColor(R.styleable.roundedimageview_border_outside_color, 54 defaultColor); 55 mBorderInsideColor = a.getColor( 56 R.styleable.roundedimageview_border_inside_color, defaultColor); 57 } 58 59 @Override 60 protected void onDraw(Canvas canvas) { 61 Drawable drawable = getDrawable(); 62 if (drawable == null) { 63 return; 64 } 65 66 if (getWidth() == 0 || getHeight() == 0) { 67 return; 68 } 69 this.measure(0, 0); 70 if (drawable.getClass() == NinePatchDrawable.class) 71 return; 72 // Bitmap b = ((BitmapDrawable) drawable).getBitmap();--------------------注意这里解决不支持xutils 73 74 Bitmap b = null; 75 if(drawable instanceof BitmapDrawable){ 76 b = ((BitmapDrawable)drawable).getBitmap() ; 77 }else if(drawable instanceof AsyncDrawable){ 78 b = Bitmap 79 .createBitmap( 80 getWidth(), 81 getHeight(), 82 drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 83 : Bitmap.Config.RGB_565); 84 Canvas canvas1 = new Canvas(b); 85 // canvas.setBitmap(bitmap); 86 drawable.setBounds(0, 0, getWidth(), 87 getHeight()); 88 drawable.draw(canvas1); 89 } 90 91 92 Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true); 93 if (defaultWidth == 0) { 94 defaultWidth = getWidth(); 95 96 } 97 if (defaultHeight == 0) { 98 defaultHeight = getHeight(); 99 } 100 // 保证重新读取图片后不会因为图片大小而改变控件宽、高的大小(针对宽、高为wrap_content布局的imageview,但会导致margin无效) 101 // if (defaultWidth != 0 && defaultHeight != 0) { 102 // LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( 103 // defaultWidth, defaultHeight); 104 // setLayoutParams(params); 105 // } 106 int radius = 0; 107 if (mBorderInsideColor != defaultColor 108 && mBorderOutsideColor != defaultColor) {// 定义画两个边框,分别为外圆边框和内圆边框 109 radius = (defaultWidth < defaultHeight ? defaultWidth 110 : defaultHeight) / 2 - 2 * mBorderThickness; 111 // 画内圆 112 drawCircleBorder(canvas, radius + mBorderThickness / 2, 113 mBorderInsideColor); 114 // 画外圆 115 drawCircleBorder(canvas, radius + mBorderThickness 116 + mBorderThickness / 2, mBorderOutsideColor); 117 } else if (mBorderInsideColor != defaultColor 118 && mBorderOutsideColor == defaultColor) {// 定义画一个边框 119 radius = (defaultWidth < defaultHeight ? defaultWidth 120 : defaultHeight) / 2 - mBorderThickness; 121 drawCircleBorder(canvas, radius + mBorderThickness / 2, 122 mBorderInsideColor); 123 } else if (mBorderInsideColor == defaultColor 124 && mBorderOutsideColor != defaultColor) {// 定义画一个边框 125 radius = (defaultWidth < defaultHeight ? defaultWidth 126 : defaultHeight) / 2 - mBorderThickness; 127 drawCircleBorder(canvas, radius + mBorderThickness / 2, 128 mBorderOutsideColor); 129 } else {// 没有边框 130 radius = (defaultWidth < defaultHeight ? defaultWidth 131 : defaultHeight) / 2; 132 } 133 Bitmap roundBitmap = getCroppedRoundBitmap(bitmap, radius); 134 canvas.drawBitmap(roundBitmap, defaultWidth / 2 - radius, defaultHeight 135 / 2 - radius, null); 136 } 137 138 /** 139 * 获取裁剪后的圆形图片 140 * 141 * @param radius 142 * 半径 143 */ 144 public Bitmap getCroppedRoundBitmap(Bitmap bmp, int radius) { 145 Bitmap scaledSrcBmp; 146 int diameter = radius * 2; 147 148 // 为了防止宽高不相等,造成圆形图片变形,因此截取长方形中处于中间位置最大的正方形图片 149 int bmpWidth = bmp.getWidth(); 150 int bmpHeight = bmp.getHeight(); 151 int squareWidth = 0, squareHeight = 0; 152 int x = 0, y = 0; 153 Bitmap squareBitmap; 154 if (bmpHeight > bmpWidth) {// 高大于宽 155 squareWidth = squareHeight = bmpWidth; 156 x = 0; 157 y = (bmpHeight - bmpWidth) / 2; 158 // 截取正方形图片 159 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, 160 squareHeight); 161 } else if (bmpHeight < bmpWidth) {// 宽大于高 162 squareWidth = squareHeight = bmpHeight; 163 x = (bmpWidth - bmpHeight) / 2; 164 y = 0; 165 squareBitmap = Bitmap.createBitmap(bmp, x, y, squareWidth, 166 squareHeight); 167 } else { 168 squareBitmap = bmp; 169 } 170 171 if (squareBitmap.getWidth() != diameter 172 || squareBitmap.getHeight() != diameter) { 173 scaledSrcBmp = Bitmap.createScaledBitmap(squareBitmap, diameter, 174 diameter, true); 175 176 } else { 177 scaledSrcBmp = squareBitmap; 178 } 179 Bitmap output = Bitmap.createBitmap(scaledSrcBmp.getWidth(), 180 scaledSrcBmp.getHeight(), Bitmap.Config.ARGB_8888); 181 Canvas canvas = new Canvas(output); 182 183 Paint paint = new Paint(); 184 Rect rect = new Rect(0, 0, scaledSrcBmp.getWidth(), 185 scaledSrcBmp.getHeight()); 186 187 paint.setAntiAlias(true); 188 paint.setFilterBitmap(true); 189 paint.setDither(true); 190 canvas.drawARGB(0, 0, 0, 0); 191 canvas.drawCircle(scaledSrcBmp.getWidth() / 2, 192 scaledSrcBmp.getHeight() / 2, scaledSrcBmp.getWidth() / 2, 193 paint); 194 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 195 canvas.drawBitmap(scaledSrcBmp, rect, rect, paint); 196 // bitmap回收(recycle导致在布局文件XML看不到效果) 197 // bmp.recycle(); 198 // squareBitmap.recycle(); 199 // scaledSrcBmp.recycle(); 200 bmp = null; 201 squareBitmap = null; 202 scaledSrcBmp = null; 203 return output; 204 } 205 206 /** 207 * 边缘画圆 208 */ 209 private void drawCircleBorder(Canvas canvas, int radius, int color) { 210 Paint paint = new Paint(); 211 /* 去锯齿 */ 212 paint.setAntiAlias(true); 213 paint.setFilterBitmap(true); 214 paint.setDither(true); 215 paint.setColor(color); 216 /* 设置paint的 style 为STROKE:空心 */ 217 paint.setStyle(Paint.Style.STROKE); 218 /* 设置paint的外框宽度 */ 219 paint.setStrokeWidth(mBorderThickness); 220 canvas.drawCircle(defaultWidth / 2, defaultHeight / 2, radius, paint); 221 } 222 223 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 <declare-styleable name="roundedimageview"> 4 <attr name="border_thickness" format="dimension" /> 5 <attr name="border_inside_color" format="color" /> 6 <attr name="border_outside_color" format="color"></attr> 7 </declare-styleable> 8 </resources>
<com.archive.xunji.widgets.RoundImageView android:id="@+id/iv_touxiang_guangchangfragment" android:layout_alignBottom="@id/tv_username_guangchangfragment" android:layout_toLeftOf="@id/tv_username_guangchangfragment" android:layout_marginRight="5dp" android:layout_width="30dp" android:layout_height="30dp" android:src="@mipmap/ic_launcher" />
圆形图片最主要的方法 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
意思是取两个元素在画布上的交集然后取上层部分显示 如此将圆形图片展示出来