1 import android.content.Context; 2 import android.graphics.Bitmap; 3 import android.graphics.BitmapShader; 4 import android.graphics.Canvas; 5 import android.graphics.Color; 6 import android.graphics.Matrix; 7 import android.graphics.Paint; 8 import android.graphics.RectF; 9 import android.graphics.Shader; 10 import android.graphics.drawable.BitmapDrawable; 11 import android.graphics.drawable.ColorDrawable; 12 import android.graphics.drawable.Drawable; 13 import android.util.AttributeSet; 14 import android.widget.ImageView; 15 16 /** 17 * 18 * @file_name: CircleImageView.java 19 * @function:自定义圆形imageview 20 */ 21 public class CircleImageView extends ImageView { 22 23 private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; 24 25 private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; 26 private static final int COLORDRAWABLE_DIMENSION = 1; 27 28 private static final int DEFAULT_BORDER_WIDTH = 0; 29 private static final int DEFAULT_BORDER_COLOR = Color.BLACK; 30 31 private final RectF mDrawableRect = new RectF(); 32 private final RectF mBorderRect = new RectF(); 33 34 private final Matrix mShaderMatrix = new Matrix(); 35 private final Paint mBitmapPaint = new Paint(); 36 private final Paint mBorderPaint = new Paint(); 37 38 private int mBorderColor = DEFAULT_BORDER_COLOR; 39 private int mBorderWidth = DEFAULT_BORDER_WIDTH; 40 41 private Bitmap mBitmap; 42 private BitmapShader mBitmapShader; 43 private int mBitmapWidth; 44 private int mBitmapHeight; 45 46 private float mDrawableRadius; 47 private float mBorderRadius; 48 49 private boolean mReady; 50 private boolean mSetupPending; 51 52 public CircleImageView(Context context) { 53 super(context); 54 } 55 56 public CircleImageView(Context context, AttributeSet attrs) { 57 this(context, attrs, 0); 58 } 59 60 public CircleImageView(Context context, AttributeSet attrs, int defStyle) { 61 super(context, attrs, defStyle); 62 super.setScaleType(SCALE_TYPE); 63 64 // TypedArray a = context.obtainStyledAttributes(attrs, 65 // R.styleable.CircleImageView, defStyle, 0); 66 // 67 // mBorderWidth = a.getDimensionPixelSize( 68 // R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); 69 // mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, 70 // DEFAULT_BORDER_COLOR); 71 72 // a.recycle(); 73 74 mReady = true; 75 76 if (mSetupPending) { 77 setup(); 78 mSetupPending = false; 79 } 80 } 81 82 @Override 83 public ScaleType getScaleType() { 84 return SCALE_TYPE; 85 } 86 87 @Override 88 public void setScaleType(ScaleType scaleType) { 89 if (scaleType != SCALE_TYPE) { 90 throw new IllegalArgumentException(String.format( 91 "ScaleType %s not supported.", scaleType)); 92 } 93 } 94 95 @Override 96 protected void onDraw(Canvas canvas) { 97 if (getDrawable() == null) { 98 return; 99 } 100 101 canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, 102 mBitmapPaint); 103 canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, 104 mBorderPaint); 105 } 106 107 @Override 108 protected void onSizeChanged(int w, int h, int oldw, int oldh) { 109 super.onSizeChanged(w, h, oldw, oldh); 110 setup(); 111 } 112 113 public int getBorderColor() { 114 return mBorderColor; 115 } 116 117 public void setBorderColor(int borderColor) { 118 if (borderColor == mBorderColor) { 119 return; 120 } 121 122 mBorderColor = borderColor; 123 mBorderPaint.setColor(mBorderColor); 124 invalidate(); 125 } 126 127 public int getBorderWidth() { 128 return mBorderWidth; 129 } 130 131 public void setBorderWidth(int borderWidth) { 132 if (borderWidth == mBorderWidth) { 133 return; 134 } 135 136 mBorderWidth = borderWidth; 137 setup(); 138 } 139 140 @Override 141 public void setImageBitmap(Bitmap bm) { 142 super.setImageBitmap(bm); 143 mBitmap = bm; 144 setup(); 145 } 146 147 @Override 148 public void setImageDrawable(Drawable drawable) { 149 super.setImageDrawable(drawable); 150 mBitmap = getBitmapFromDrawable(drawable); 151 setup(); 152 } 153 154 @Override 155 public void setImageResource(int resId) { 156 super.setImageResource(resId); 157 mBitmap = getBitmapFromDrawable(getDrawable()); 158 setup(); 159 } 160 161 private Bitmap getBitmapFromDrawable(Drawable drawable) { 162 if (drawable == null) { 163 return null; 164 } 165 166 if (drawable instanceof BitmapDrawable) { 167 return ((BitmapDrawable) drawable).getBitmap(); 168 } 169 170 try { 171 Bitmap bitmap; 172 173 if (drawable instanceof ColorDrawable) { 174 bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, 175 COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); 176 } else { 177 bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), 178 drawable.getIntrinsicHeight(), BITMAP_CONFIG); 179 } 180 181 Canvas canvas = new Canvas(bitmap); 182 drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 183 drawable.draw(canvas); 184 return bitmap; 185 } catch (OutOfMemoryError e) { 186 return null; 187 } 188 } 189 190 private void setup() { 191 if (!mReady) { 192 mSetupPending = true; 193 return; 194 } 195 196 if (mBitmap == null) { 197 return; 198 } 199 200 mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, 201 Shader.TileMode.CLAMP); 202 203 mBitmapPaint.setAntiAlias(true); 204 mBitmapPaint.setShader(mBitmapShader); 205 206 mBorderPaint.setStyle(Paint.Style.STROKE); 207 mBorderPaint.setAntiAlias(true); 208 mBorderPaint.setColor(mBorderColor); 209 mBorderPaint.setStrokeWidth(mBorderWidth); 210 211 mBitmapHeight = mBitmap.getHeight(); 212 mBitmapWidth = mBitmap.getWidth(); 213 214 mBorderRect.set(0, 0, getWidth(), getHeight()); 215 mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, 216 (mBorderRect.width() - mBorderWidth) / 2); 217 218 mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() 219 - mBorderWidth, mBorderRect.height() - mBorderWidth); 220 mDrawableRadius = Math.min(mDrawableRect.height() / 2, 221 mDrawableRect.width() / 2); 222 223 updateShaderMatrix(); 224 invalidate(); 225 } 226 227 private void updateShaderMatrix() { 228 float scale; 229 float dx = 0; 230 float dy = 0; 231 232 mShaderMatrix.set(null); 233 234 if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() 235 * mBitmapHeight) { 236 scale = mDrawableRect.height() / (float) mBitmapHeight; 237 dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; 238 } else { 239 scale = mDrawableRect.width() / (float) mBitmapWidth; 240 dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; 241 } 242 243 mShaderMatrix.setScale(scale, scale); 244 mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, 245 (int) (dy + 0.5f) + mBorderWidth); 246 247 mBitmapShader.setLocalMatrix(mShaderMatrix); 248 } 249 250 }