zoukankan      html  css  js  c++  java
  • 自定义圆角ImageView控件

    这个就当工具类用吧,因为直接是继承的ImageView.所以也具备了ImageView所有的特点,不同的是,可以自动裁剪成圆角图片。看效果吧。

    效果还是不错的。使用方式:

    直接在配置中添加依赖

    1 compile 'de.hdodenhof:circleimageview:2.1.0'

    并且查看其源码,思路也非常简单清晰:

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

    xml使用方式实例:

     1 <LinearLayout
     2         android:layout_width="match_parent"
     3         android:layout_height="200dp"
     4         android:background="@color/color_main"
     5         android:gravity="center"
     6         android:orientation="vertical">
     7 
     8         <de.hdodenhof.circleimageview.CircleImageView
     9             android:id="@+id/profile_image"
    10             android:layout_width="96dp"
    11             android:layout_height="96dp"
    12             android:src="@mipmap/timg"
    13             app:civ_border_color="@color/color_white"
    14             app:civ_border_width="2dp" />
    15 
    16 </LinearLayout>
  • 相关阅读:
    chrome浏览页面常用快捷键 && 常见的HTTP状态码
    hasCode详解
    队例初始化问题(Queue)
    新手问题--双链表最后一个节点无法删除问题
    高级排序--快速排序
    高级排序--归并排序
    高级排序--希尔排序
    简单排序--插入排序
    简单排序--选择排序
    简单排序--冒泡排序
  • 原文地址:https://www.cnblogs.com/huolongluo/p/6360831.html
Copyright © 2011-2022 走看看