安卓自定义圆形图片控件的使用(hdodenhof/CircleImageView)

控件的来源:https://github.com/hdodenhof/CircleImageView

感兴趣的可以去看看,我只说一下怎么使用:

效果图:

在自己的项目中使用的话,需要写一个类class CircleImageView extends ImageView :

具体如下,只是使用的话,复制过来就好,注意改一下包名:

  1 package de.hdodenhof.circleimageview;
  2 
  3 import android.content.Context;
  4 import android.content.res.TypedArray;
  5 import android.graphics.Bitmap;
  6 import android.graphics.BitmapShader;
  7 import android.graphics.Canvas;
  8 import android.graphics.Color;
  9 import android.graphics.ColorFilter;
 10 import android.graphics.Matrix;
 11 import android.graphics.Paint;
 12 import android.graphics.RectF;
 13 import android.graphics.Shader;
 14 import android.graphics.drawable.BitmapDrawable;
 15 import android.graphics.drawable.ColorDrawable;
 16 import android.graphics.drawable.Drawable;
 17 import android.net.Uri;
 18 import android.support.annotation.ColorInt;
 19 import android.support.annotation.ColorRes;
 20 import android.support.annotation.DrawableRes;
 21 import android.util.AttributeSet;
 22 import android.widget.ImageView;
 23 
 24 public class CircleImageView extends ImageView {
 25 
 26     private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
 27 
 28     private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
 29     private static final int COLORDRAWABLE_DIMENSION = 2;
 30 
 31     private static final int DEFAULT_BORDER_WIDTH = 0;
 32     private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
 33     private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;
 34     private static final boolean DEFAULT_BORDER_OVERLAY = false;
 35 
 36     private final RectF mDrawableRect = new RectF();
 37     private final RectF mBorderRect = new RectF();
 38 
 39     private final Matrix mShaderMatrix = new Matrix();
 40     private final Paint mBitmapPaint = new Paint();
 41     private final Paint mBorderPaint = new Paint();
 42     private final Paint mFillPaint = new Paint();
 43 
 44     private int mBorderColor = DEFAULT_BORDER_COLOR;
 45     private int mBorderWidth = DEFAULT_BORDER_WIDTH;
 46     private int mFillColor = DEFAULT_FILL_COLOR;
 47 
 48     private Bitmap mBitmap;
 49     private BitmapShader mBitmapShader;
 50     private int mBitmapWidth;
 51     private int mBitmapHeight;
 52 
 53     private float mDrawableRadius;
 54     private float mBorderRadius;
 55 
 56     private ColorFilter mColorFilter;
 57 
 58     private boolean mReady;
 59     private boolean mSetupPending;
 60     private boolean mBorderOverlay;
 61     private boolean mDisableCircularTransformation;
 62 
 63     public CircleImageView(Context context) {
 64         super(context);
 65 
 66         init();
 67     }
 68 
 69     public CircleImageView(Context context, AttributeSet attrs) {
 70         this(context, attrs, 0);
 71     }
 72 
 73     public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
 74         super(context, attrs, defStyle);
 75 
 76         TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
 77 
 78         mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);
 79         mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);
 80         mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);
 81         mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR);
 82 
 83         a.recycle();
 84 
 85         init();
 86     }
 87 
 88     private void init() {
 89         super.setScaleType(SCALE_TYPE);
 90         mReady = true;
 91 
 92         if (mSetupPending) {
 93             setup();
 94             mSetupPending = false;
 95         }
 96     }
 97 
 98     @Override
 99     public ScaleType getScaleType() {
100         return SCALE_TYPE;
101     }
102 
103     @Override
104     public void setScaleType(ScaleType scaleType) {
105         if (scaleType != SCALE_TYPE) {
106             throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
107         }
108     }
109 
110     @Override
111     public void setAdjustViewBounds(boolean adjustViewBounds) {
112         if (adjustViewBounds) {
113             throw new IllegalArgumentException("adjustViewBounds not supported.");
114         }
115     }
116 
117     @Override
118     protected void onDraw(Canvas canvas) {
119         if (mDisableCircularTransformation) {
120             super.onDraw(canvas);
121             return;
122         }
123 
124         if (mBitmap == null) {
125             return;
126         }
127 
128         if (mFillColor != Color.TRANSPARENT) {
129             canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);
130         }
131         canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);
132         if (mBorderWidth > 0) {
133             canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);
134         }
135     }
136 
137     @Override
138     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
139         super.onSizeChanged(w, h, oldw, oldh);
140         setup();
141     }
142 
143     @Override
144     public void setPadding(int left, int top, int right, int bottom) {
145         super.setPadding(left, top, right, bottom);
146         setup();
147     }
148 
149     @Override
150     public void setPaddingRelative(int start, int top, int end, int bottom) {
151         super.setPaddingRelative(start, top, end, bottom);
152         setup();
153     }
154 
155     public int getBorderColor() {
156         return mBorderColor;
157     }
158 
159     public void setBorderColor(@ColorInt int borderColor) {
160         if (borderColor == mBorderColor) {
161             return;
162         }
163 
164         mBorderColor = borderColor;
165         mBorderPaint.setColor(mBorderColor);
166         invalidate();
167     }
168 
169     /**
170      * @deprecated Use {@link #setBorderColor(int)} instead
171      */
172     @Deprecated
173     public void setBorderColorResource(@ColorRes int borderColorRes) {
174         setBorderColor(getContext().getResources().getColor(borderColorRes));
175     }
176 
177     /**
178      * Return the color drawn behind the circle-shaped drawable.
179      *
180      * @return The color drawn behind the drawable
181      *
182      * @deprecated Fill color support is going to be removed in the future
183      */
184     @Deprecated
185     public int getFillColor() {
186         return mFillColor;
187     }
188 
189     /**
190      * Set a color to be drawn behind the circle-shaped drawable. Note that
191      * this has no effect if the drawable is opaque or no drawable is set.
192      *
193      * @param fillColor The color to be drawn behind the drawable
194      *
195      * @deprecated Fill color support is going to be removed in the future
196      */
197     @Deprecated
198     public void setFillColor(@ColorInt int fillColor) {
199         if (fillColor == mFillColor) {
200             return;
201         }
202 
203         mFillColor = fillColor;
204         mFillPaint.setColor(fillColor);
205         invalidate();
206     }
207 
208     /**
209      * Set a color to be drawn behind the circle-shaped drawable. Note that
210      * this has no effect if the drawable is opaque or no drawable is set.
211      *
212      * @param fillColorRes The color resource to be resolved to a color and
213      *                     drawn behind the drawable
214      *
215      * @deprecated Fill color support is going to be removed in the future
216      */
217     @Deprecated
218     public void setFillColorResource(@ColorRes int fillColorRes) {
219         setFillColor(getContext().getResources().getColor(fillColorRes));
220     }
221 
222     public int getBorderWidth() {
223         return mBorderWidth;
224     }
225 
226     public void setBorderWidth(int borderWidth) {
227         if (borderWidth == mBorderWidth) {
228             return;
229         }
230 
231         mBorderWidth = borderWidth;
232         setup();
233     }
234 
235     public boolean isBorderOverlay() {
236         return mBorderOverlay;
237     }
238 
239     public void setBorderOverlay(boolean borderOverlay) {
240         if (borderOverlay == mBorderOverlay) {
241             return;
242         }
243 
244         mBorderOverlay = borderOverlay;
245         setup();
246     }
247 
248     public boolean isDisableCircularTransformation() {
249         return mDisableCircularTransformation;
250     }
251 
252     public void setDisableCircularTransformation(boolean disableCircularTransformation) {
253         if (mDisableCircularTransformation == disableCircularTransformation) {
254             return;
255         }
256 
257         mDisableCircularTransformation = disableCircularTransformation;
258         initializeBitmap();
259     }
260 
261     @Override
262     public void setImageBitmap(Bitmap bm) {
263         super.setImageBitmap(bm);
264         initializeBitmap();
265     }
266 
267     @Override
268     public void setImageDrawable(Drawable drawable) {
269         super.setImageDrawable(drawable);
270         initializeBitmap();
271     }
272 
273     @Override
274     public void setImageResource(@DrawableRes int resId) {
275         super.setImageResource(resId);
276         initializeBitmap();
277     }
278 
279     @Override
280     public void setImageURI(Uri uri) {
281         super.setImageURI(uri);
282         initializeBitmap();
283     }
284 
285     @Override
286     public void setColorFilter(ColorFilter cf) {
287         if (cf == mColorFilter) {
288             return;
289         }
290 
291         mColorFilter = cf;
292         applyColorFilter();
293         invalidate();
294     }
295 
296     @Override
297     public ColorFilter getColorFilter() {
298         return mColorFilter;
299     }
300 
301     private void applyColorFilter() {
302         if (mBitmapPaint != null) {
303             mBitmapPaint.setColorFilter(mColorFilter);
304         }
305     }
306 
307     private Bitmap getBitmapFromDrawable(Drawable drawable) {
308         if (drawable == null) {
309             return null;
310         }
311 
312         if (drawable instanceof BitmapDrawable) {
313             return ((BitmapDrawable) drawable).getBitmap();
314         }
315 
316         try {
317             Bitmap bitmap;
318 
319             if (drawable instanceof ColorDrawable) {
320                 bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
321             } else {
322                 bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
323             }
324 
325             Canvas canvas = new Canvas(bitmap);
326             drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
327             drawable.draw(canvas);
328             return bitmap;
329         } catch (Exception e) {
330             e.printStackTrace();
331             return null;
332         }
333     }
334 
335     private void initializeBitmap() {
336         if (mDisableCircularTransformation) {
337             mBitmap = null;
338         } else {
339             mBitmap = getBitmapFromDrawable(getDrawable());
340         }
341         setup();
342     }
343 
344     private void setup() {
345         if (!mReady) {
346             mSetupPending = true;
347             return;
348         }
349 
350         if (getWidth() == 0 && getHeight() == 0) {
351             return;
352         }
353 
354         if (mBitmap == null) {
355             invalidate();
356             return;
357         }
358 
359         mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
360 
361         mBitmapPaint.setAntiAlias(true);
362         mBitmapPaint.setShader(mBitmapShader);
363 
364         mBorderPaint.setStyle(Paint.Style.STROKE);
365         mBorderPaint.setAntiAlias(true);
366         mBorderPaint.setColor(mBorderColor);
367         mBorderPaint.setStrokeWidth(mBorderWidth);
368 
369         mFillPaint.setStyle(Paint.Style.FILL);
370         mFillPaint.setAntiAlias(true);
371         mFillPaint.setColor(mFillColor);
372 
373         mBitmapHeight = mBitmap.getHeight();
374         mBitmapWidth = mBitmap.getWidth();
375 
376         mBorderRect.set(calculateBounds());
377         mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);
378 
379         mDrawableRect.set(mBorderRect);
380         if (!mBorderOverlay && mBorderWidth > 0) {
381             mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);
382         }
383         mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);
384 
385         applyColorFilter();
386         updateShaderMatrix();
387         invalidate();
388     }
389 
390     private RectF calculateBounds() {
391         int availableWidth  = getWidth() - getPaddingLeft() - getPaddingRight();
392         int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();
393 
394         int sideLength = Math.min(availableWidth, availableHeight);
395 
396         float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;
397         float top = getPaddingTop() + (availableHeight - sideLength) / 2f;
398 
399         return new RectF(left, top, left + sideLength, top + sideLength);
400     }
401 
402     private void updateShaderMatrix() {
403         float scale;
404         float dx = 0;
405         float dy = 0;
406 
407         mShaderMatrix.set(null);
408 
409         if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
410             scale = mDrawableRect.height() / (float) mBitmapHeight;
411             dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
412         } else {
413             scale = mDrawableRect.width() / (float) mBitmapWidth;
414             dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
415         }
416 
417         mShaderMatrix.setScale(scale, scale);
418         mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
419 
420         mBitmapShader.setLocalMatrix(mShaderMatrix);
421     }
422 
423 }

到attr.xml中declare-styleable申明自定义控件属性

文件定义在res/values/attr.xml:

1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3     <declare-styleable name="CircleImageView">
4         <attr name="civ_border_width" format="dimension" />
5         <attr name="civ_border_color" format="color" />
6         <attr name="civ_border_overlay" format="boolean" />
7         <attr name="civ_fill_color" format="color" />
8     </declare-styleable>
9 </resources>

在Gradle中添加(注意更改成自己的包名):

1 dependencies {
2     ...
3     compile 'de.hdodenhof:circleimageview:2.1.0'
4 }

然后就能使用了

1 <de.hdodenhof.circleimageview.CircleImageView
2             android:layout_width="160dp"
3             android:layout_height="160dp"
4             android:layout_centerInParent="true"
5             android:src="@drawable/hugh"
6             app:civ_border_width="2dp"
7             app:civ_border_color="@color/dark" />

和一般的控件使用方式是相同的。

posted @ 2016-10-06 09:18  墨血  阅读(30462)  评论(0编辑  收藏  举报