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 }