美文网首页
1、自定义圆形的 ImageView

1、自定义圆形的 ImageView

作者: 大佬不是大佬 | 来源:发表于2019-07-24 22:42 被阅读0次

        事先声明,并非本人原创,是在某GITHUB找到的代码实现功能后做的笔记,由于时间过去太久,早已忘记所参考的 GitHub地址,如有侵权,立即删除。


    1、activity.main.xml代码如下:

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:orientation="vertical">

        <RelativeLayout

            android:id="@+id/qqLayout"

            android:layout_width="match_parent"

            android:layout_height="120dp"

            android:background="#e5e5e5">

            <TextView

                android:id="@+id/text1"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_alignParentLeft="true"

                android:layout_centerVertical="true"

                android:layout_marginLeft="20dp"

                android:text="1、仿QQ头像上传"

                android:textColor="#173070"

                android:textSize="16sp" />

            <com.example.app_test.CircleImageView

                android:id="@+id/head_image1"

                android:layout_width="80dp"

                android:layout_height="80dp"

                android:layout_centerVertical="true"

                android:layout_alignParentRight="true"

                android:layout_marginRight="50dp"

                android:src="@drawable/qq" />

        </RelativeLayout>

        <View

            android:layout_width="match_parent"

            android:layout_height="1px"

            android:background="#173070" />

        <com.example.app_test.CircleImageView

            android:layout_width="80dp"

            android:layout_height="80dp"

            android:layout_centerVertical="true"

            android:layout_alignParentRight="true"

            android:layout_marginRight="50dp"

            android:src="@drawable/caocao" />

    </LinearLayout>


    2、新建一个 CircleImageView,自定义控件。

    public class CircleImageView extends AppCompatImageView{

        private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;

        private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;

        private static final int COLORDRAWABLE_DIMENSION = 2;

        private static final int DEFAULT_BORDER_WIDTH = 0;

        private static final int DEFAULT_BORDER_COLOR = Color.BLACK;

        private static final int DEFAULT_FILL_COLOR = Color.TRANSPARENT;

        private static final boolean DEFAULT_BORDER_OVERLAY = false;

        private final RectF mDrawableRect = new RectF();

        private final RectF mBorderRect = new RectF();

        private final Matrix mShaderMatrix = new Matrix();

        private final Paint mBitmapPaint = new Paint();

        private final Paint mBorderPaint = new Paint();

        private final Paint mFillPaint = new Paint();

        private int mBorderColor = DEFAULT_BORDER_COLOR;

        private int mBorderWidth = DEFAULT_BORDER_WIDTH;

        private int mFillColor = DEFAULT_FILL_COLOR;

        private Bitmap mBitmap;

        private BitmapShader mBitmapShader;

        private int mBitmapWidth;

        private int mBitmapHeight;

        private float mDrawableRadius;

        private float mBorderRadius;

        private ColorFilter mColorFilter;

        private boolean mReady;

        private boolean mSetupPending;

        private boolean mBorderOverlay;

        private boolean mDisableCircularTransformation;

        public CircleImageView(Context context) {

            super(context);

            init();

        }

        public CircleImageView(Context context, AttributeSet attrs) {

            this(context, attrs, 0);

        }

        public CircleImageView(Context context, AttributeSet attrs, int defStyle) {

            super(context, attrs, defStyle);

            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);

            mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH);

            mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR);

            mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY);

            mFillColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, DEFAULT_FILL_COLOR);

            a.recycle();

            init();

        }

        private void init() {

            super.setScaleType(SCALE_TYPE);

            mReady = true;

            if (mSetupPending) {

                setup();

                mSetupPending = false;

            }

        }

        @Override

        public ScaleType getScaleType() {

            return SCALE_TYPE;

        }

        @Override

        public void setScaleType(ScaleType scaleType) {

            if (scaleType != SCALE_TYPE) {

                throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));

            }

        }

        @Override

        public void setAdjustViewBounds(boolean adjustViewBounds) {

            if (adjustViewBounds) {

                throw new IllegalArgumentException("adjustViewBounds not supported.");

            }

        }

        @Override

        protected void onDraw(Canvas canvas) {

            if (mDisableCircularTransformation) {

                super.onDraw(canvas);

                return;

            }

            if (mBitmap == null) {

                return;

            }

            if (mFillColor != Color.TRANSPARENT) {

                canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mFillPaint);

            }

            canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint);

            if (mBorderWidth > 0) {

                canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint);

            }

        }

        @Override

        protected void onSizeChanged(int w, int h, int oldw, int oldh) {

            super.onSizeChanged(w, h, oldw, oldh);

            setup();

        }

        @Override

        public void setPadding(int left, int top, int right, int bottom) {

            super.setPadding(left, top, right, bottom);

            setup();

        }

        @Override

        public void setPaddingRelative(int start, int top, int end, int bottom) {

            super.setPaddingRelative(start, top, end, bottom);

            setup();

        }

        public int getBorderColor() {

            return mBorderColor;

        }

        public void setBorderColor(@ColorInt int borderColor) {

            if (borderColor == mBorderColor) {

                return;

            }

            mBorderColor = borderColor;

            mBorderPaint.setColor(mBorderColor);

            invalidate();

        }

        /**

        * @deprecated Use {@link #setBorderColor(int)} instead

        */

        @Deprecated

        public void setBorderColorResource(@ColorRes int borderColorRes) {

            setBorderColor(getContext().getResources().getColor(borderColorRes));

        }

        /**

        * Return the color drawn behind the circle-shaped drawable.

        *

        * @return The color drawn behind the drawable

        *

        * @deprecated Fill color support is going to be removed in the future

        */

        @Deprecated

        public int getFillColor() {

            return mFillColor;

        }

        /**

        * Set a color to be drawn behind the circle-shaped drawable. Note that

        * this has no effect if the drawable is opaque or no drawable is set.

        *

        * @param fillColor The color to be drawn behind the drawable

        *

        * @deprecated Fill color support is going to be removed in the future

        */

        @Deprecated

        public void setFillColor(@ColorInt int fillColor) {

            if (fillColor == mFillColor) {

                return;

            }

            mFillColor = fillColor;

            mFillPaint.setColor(fillColor);

            invalidate();

        }

        /**

        * Set a color to be drawn behind the circle-shaped drawable. Note that

        * this has no effect if the drawable is opaque or no drawable is set.

        *

        * @param fillColorRes The color resource to be resolved to a color and

        *                    drawn behind the drawable

        *

        * @deprecated Fill color support is going to be removed in the future

        */

        @Deprecated

        public void setFillColorResource(@ColorRes int fillColorRes) {

            setFillColor(getContext().getResources().getColor(fillColorRes));

        }

        public int getBorderWidth() {

            return mBorderWidth;

        }

        public void setBorderWidth(int borderWidth) {

            if (borderWidth == mBorderWidth) {

                return;

            }

            mBorderWidth = borderWidth;

            setup();

        }

        public boolean isBorderOverlay() {

            return mBorderOverlay;

        }

        public void setBorderOverlay(boolean borderOverlay) {

            if (borderOverlay == mBorderOverlay) {

                return;

            }

            mBorderOverlay = borderOverlay;

            setup();

        }

        public boolean isDisableCircularTransformation() {

            return mDisableCircularTransformation;

        }

        public void setDisableCircularTransformation(boolean disableCircularTransformation) {

            if (mDisableCircularTransformation == disableCircularTransformation) {

                return;

            }

            mDisableCircularTransformation = disableCircularTransformation;

            initializeBitmap();

        }

        @Override

        public void setImageBitmap(Bitmap bm) {

            super.setImageBitmap(bm);

            initializeBitmap();

        }

        @Override

        public void setImageDrawable(Drawable drawable) {

            super.setImageDrawable(drawable);

            initializeBitmap();

        }

        @Override

        public void setImageResource(@DrawableRes int resId) {

            super.setImageResource(resId);

            initializeBitmap();

        }

        @Override

        public void setImageURI(Uri uri) {

            super.setImageURI(uri);

            initializeBitmap();

        }

        @Override

        public void setColorFilter(ColorFilter cf) {

            if (cf == mColorFilter) {

                return;

            }

            mColorFilter = cf;

            applyColorFilter();

            invalidate();

        }

        @Override

        public ColorFilter getColorFilter() {

            return mColorFilter;

        }

        private void applyColorFilter() {

            if (mBitmapPaint != null) {

                mBitmapPaint.setColorFilter(mColorFilter);

            }

        }

        private Bitmap getBitmapFromDrawable(Drawable drawable) {

            if (drawable == null) {

                return null;

            }

            if (drawable instanceof BitmapDrawable) {

                return ((BitmapDrawable) drawable).getBitmap();

            }

            try {

                Bitmap bitmap;

                if (drawable instanceof ColorDrawable) {

                    bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);

                } else {

                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);

                }

                Canvas canvas = new Canvas(bitmap);

                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());

                drawable.draw(canvas);

                return bitmap;

            } catch (Exception e) {

                e.printStackTrace();

                return null;

            }

        }

        private void initializeBitmap() {

            if (mDisableCircularTransformation) {

                mBitmap = null;

            } else {

                mBitmap = getBitmapFromDrawable(getDrawable());

            }

            setup();

        }

        private void setup() {

            if (!mReady) {

                mSetupPending = true;

                return;

            }

            if (getWidth() == 0 && getHeight() == 0) {

                return;

            }

            if (mBitmap == null) {

                invalidate();

                return;

            }

            mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

            mBitmapPaint.setAntiAlias(true);

            mBitmapPaint.setShader(mBitmapShader);

            mBorderPaint.setStyle(Paint.Style.STROKE);

            mBorderPaint.setAntiAlias(true);

            mBorderPaint.setColor(mBorderColor);

            mBorderPaint.setStrokeWidth(mBorderWidth);

            mFillPaint.setStyle(Paint.Style.FILL);

            mFillPaint.setAntiAlias(true);

            mFillPaint.setColor(mFillColor);

            mBitmapHeight = mBitmap.getHeight();

            mBitmapWidth = mBitmap.getWidth();

            mBorderRect.set(calculateBounds());

            mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f);

            mDrawableRect.set(mBorderRect);

            if (!mBorderOverlay && mBorderWidth > 0) {

                mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f);

            }

            mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f);

            applyColorFilter();

            updateShaderMatrix();

            invalidate();

        }

        private RectF calculateBounds() {

            int availableWidth  = getWidth() - getPaddingLeft() - getPaddingRight();

            int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom();

            int sideLength = Math.min(availableWidth, availableHeight);

            float left = getPaddingLeft() + (availableWidth - sideLength) / 2f;

            float top = getPaddingTop() + (availableHeight - sideLength) / 2f;

            return new RectF(left, top, left + sideLength, top + sideLength);

        }

        private void updateShaderMatrix() {

            float scale;

            float dx = 0;

            float dy = 0;

            mShaderMatrix.set(null);

            if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {

                scale = mDrawableRect.height() / (float) mBitmapHeight;

                dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;

            } else {

                scale = mDrawableRect.width() / (float) mBitmapWidth;

                dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;

            }

            mShaderMatrix.setScale(scale, scale);

            mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);

            mBitmapShader.setLocalMatrix(mShaderMatrix);

        }

    }


    3、对应 CircleImageView的自定义属性配置文件XML。

    <resources>

        <declare-styleable name="CircleImageView">

            <attr name="civ_border_width" format="dimension" />

            <attr name="civ_border_color" format="color" />

            <attr name="civ_border_overlay" format="boolean" />

            <attr name="civ_fill_color" format="color" />

        </declare-styleable>

    </resources>

        最后效果图:

    相关文章

      网友评论

          本文标题:1、自定义圆形的 ImageView

          本文链接:https://www.haomeiwen.com/subject/fxkqrctx.html