zoukankan      html  css  js  c++  java
  • 安卓自定义圆形图片控件的使用(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" />

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

  • 相关阅读:
    Well, that was fun! An adventure in WCF, SSL, and Host Headers (转)
    算法还重要吗?
    Silverlight测试——利用Ranorex实现数据驱动测试
    MSSQl分布式查询
    Silverlight 4 CHM中文离线文档已提供下载
    快速打包你的应用程序——Inno Setup
    IE 9 Beta 测试Bug
    IE 9 Bate 泄露版
    Windows PowerShell初体验——.NET对象支持
    多样化实现Windows Phone 7本地数据库访问<2>
  • 原文地址:https://www.cnblogs.com/mo-xue/p/5933429.html
Copyright © 2011-2022 走看看