首页 > 代码库 > 安卓自定义圆形图片控件的使用(hdodenhof/CircleImageView)

安卓自定义圆形图片控件的使用(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     @Override104     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     @Override111     public void setAdjustViewBounds(boolean adjustViewBounds) {112         if (adjustViewBounds) {113             throw new IllegalArgumentException("adjustViewBounds not supported.");114         }115     }116 117     @Override118     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     @Override138     protected void onSizeChanged(int w, int h, int oldw, int oldh) {139         super.onSizeChanged(w, h, oldw, oldh);140         setup();141     }142 143     @Override144     public void setPadding(int left, int top, int right, int bottom) {145         super.setPadding(left, top, right, bottom);146         setup();147     }148 149     @Override150     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)} instead171      */172     @Deprecated173     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 drawable181      *182      * @deprecated Fill color support is going to be removed in the future183      */184     @Deprecated185     public int getFillColor() {186         return mFillColor;187     }188 189     /**190      * Set a color to be drawn behind the circle-shaped drawable. Note that191      * 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 drawable194      *195      * @deprecated Fill color support is going to be removed in the future196      */197     @Deprecated198     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 that210      * 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 and213      *                     drawn behind the drawable214      *215      * @deprecated Fill color support is going to be removed in the future216      */217     @Deprecated218     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     @Override262     public void setImageBitmap(Bitmap bm) {263         super.setImageBitmap(bm);264         initializeBitmap();265     }266 267     @Override268     public void setImageDrawable(Drawable drawable) {269         super.setImageDrawable(drawable);270         initializeBitmap();271     }272 273     @Override274     public void setImageResource(@DrawableRes int resId) {275         super.setImageResource(resId);276         initializeBitmap();277     }278 279     @Override280     public void setImageURI(Uri uri) {281         super.setImageURI(uri);282         initializeBitmap();283     }284 285     @Override286     public void setColorFilter(ColorFilter cf) {287         if (cf == mColorFilter) {288             return;289         }290 291         mColorFilter = cf;292         applyColorFilter();293         invalidate();294     }295 296     @Override297     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.CircleImageView2             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" />

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

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