自定义带 vip 标识的 圆形头像(圆形ImageView)

2023-02-10 18:55:37 浏览数 (1)

代码语言:javascript复制
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;

import com.ccvideo.R;

public class RoundImageView extends ImageView {
    private Paint mPaint;
    private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);

    private WeakReference<Bitmap> mWeakBitmap;
    private WeakReference<Bitmap> mMaskWeakBitmap;
    private WeakReference<Canvas> mWeakCanvas;

    public static final int TYPE_CIRCLE = 0;
    public static final int TYPE_ROUND = 1;

    private static final int BORDER_RADIUS_DEFAULT = 10;
    private static final int BORDER_WIDTH_DEFAULT = 0;
    private static final int BORDER_COLOR_DEFAULT = R.color.black_alpha_percent_10;

    private int mShapeType;
    private int mBorderRadius;
    private int mBorderWidth;
    private int mBorderColor;
    private int mOverLayColor;

    public RoundImageView(Context context, int BorderWidth, int BorderColor) {
        this(context, null);
        this.mBorderWidth = BorderWidth;
        this.mBorderColor = BorderColor;
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    public RoundImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);

        mBorderRadius = a.getDimensionPixelSize(R.styleable.RoundImageView_border_radius,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        BORDER_RADIUS_DEFAULT, getResources().getDisplayMetrics()));// Default 10dp
        mShapeType = a.getInt(R.styleable.RoundImageView_type, TYPE_CIRCLE);
        mBorderWidth = a.getDimensionPixelSize(R.styleable.RoundImageView_border_width,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        BORDER_WIDTH_DEFAULT, getResources().getDisplayMetrics()));
        mBorderColor = a.getColor(R.styleable.RoundImageView_border_color, BORDER_COLOR_DEFAULT);
        mOverLayColor = a.getColor(R.styleable.RoundImageView_overlay, android.R.color.transparent);

        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (mShapeType == TYPE_CIRCLE) {
            int width = Math.min(getMeasuredWidth(), getMeasuredHeight());
            // setMeasuredDimension(width, width);
        }

    }

    @Override
    public void invalidate() {
        mWeakBitmap = null;
        mMaskWeakBitmap = null;
        mWeakCanvas = null;
        super.invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null || getWidth() == 0 || getHeight() == 0) {
            return;
        }

        Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();
        if (bitmap == null || bitmap.isRecycled()) {
            bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        }

        Canvas drawCanvas = mWeakCanvas == null ? null : mWeakCanvas.get();
        if (drawCanvas == null) {
            drawCanvas = new Canvas(bitmap);
        }

        float scale = 1.0f;
        int drawableWidth = drawable.getIntrinsicWidth();
        int drawableHeight = drawable.getIntrinsicHeight();
        if (mShapeType == TYPE_ROUND) {
            scale = Math.max(getWidth() * 1.0f / drawableWidth, getHeight() * 1.0f / drawableHeight);
        } else {
            scale = getWidth() * 1.0f / Math.min(drawableWidth, drawableHeight);
        }
        drawable.setBounds(0, 0, (int) (scale * drawableWidth), (int) (scale * drawableHeight));
        drawable.draw(drawCanvas);

        mPaint.reset();
        mPaint.setColor(mOverLayColor);
        drawCanvas.drawColor(mOverLayColor);

        mPaint.reset();
        mPaint.setFilterBitmap(false);
        mPaint.setXfermode(mXfermode);

        Bitmap maskBitmap = mMaskWeakBitmap == null ? null : mMaskWeakBitmap.get();
        if (maskBitmap == null || maskBitmap.isRecycled()) {
            maskBitmap = getBitmap();
            mMaskWeakBitmap = new WeakReference<Bitmap>(maskBitmap);
        }
        drawCanvas.drawBitmap(maskBitmap, 0, 0, mPaint);
        mPaint.setXfermode(null);
        if (mBorderWidth > 0) {
            drawCircleBorder(drawCanvas);
        }

        canvas.drawBitmap(bitmap, 0, 0, null);
    }

    private Bitmap getBitmap() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);

        if (mShapeType == TYPE_ROUND) {
            canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),
                    mBorderRadius, mBorderRadius, paint);
        } else {
            canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - mBorderWidth, paint);
        }

        return bitmap;
    }

    private void drawCircleBorder(Canvas canvas) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        paint.setColor(mBorderColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(mBorderWidth);
        if (mShapeType == TYPE_ROUND) {
            canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()),
                    mBorderRadius, mBorderRadius, paint);
        } else {
            canvas.drawCircle(getWidth() / 2, getWidth() / 2, (getWidth() - mBorderWidth) / 2, paint);
        }
    }

    public void setBorderWidth(int borderWidth) {
        this.mBorderWidth = mBorderWidth;
    }

    public void setBorderColor(int borderColor) {
        this.mBorderColor = mBorderColor;
    }
}

代码语言:javascript复制
package com.yizhibo.video.view;
import java.lang.ref.WeakReference;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.ImageView;

import com.ccvideo.R;

public class MyUserPhoto extends ImageView {
    private static final int BORDER_SMALL_WIDTH_DEFAULT = 10;
    private static final int BORDER_SMALL_HEIGHT_DEFAULT = 10;
    private static final int IS_VIP = 1;

    private static final int BORDER_WIDTH_DEFAULT = 0;
    private static final int BORDER_COLOR_DEFAULT = R.color.black_alpha_percent_10;

    private int mSmallImageWidth;
    private int mSmallImageHeight;
    private int mIsVip;
    private int mBorderWidth;
    private int mBorderColor;
    private int mSmallIconResId;

    private Paint mPaint;
    private Xfermode mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);

    private WeakReference<Bitmap> mWeakBitmap;
    private WeakReference<Bitmap> mMaskWeakBitmap;
    private WeakReference<Canvas> mWeakCanvas;

    public MyUserPhoto(Context context) {
        super(context);
    }

    public MyUserPhoto(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyUserPhoto);
        mSmallImageHeight = a.getDimensionPixelSize(R.styleable.MyUserPhoto_small_height,
                BORDER_SMALL_HEIGHT_DEFAULT);
        mSmallImageWidth = a.getDimensionPixelSize(R.styleable.MyUserPhoto_small_width,
                BORDER_SMALL_WIDTH_DEFAULT);
        mIsVip = a.getInt(R.styleable.MyUserPhoto_is_vip, 0);
        mSmallIconResId = a.getResourceId(R.styleable.MyUserPhoto_small_icon,
                R.drawable.floating_screen_v);

        mBorderWidth = a.getDimensionPixelSize(R.styleable.MyUserPhoto_border_width,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                        BORDER_WIDTH_DEFAULT, getResources().getDisplayMetrics()));
        mBorderColor = a.getColor(R.styleable.MyUserPhoto_border_color, BORDER_COLOR_DEFAULT);

        setWillNotDraw(false);

        a.recycle();
    }

    @Override
    public void invalidate() {
        mWeakBitmap = null;
        mMaskWeakBitmap = null;
        mWeakCanvas = null;
        super.invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable == null || getWidth() == 0 || getHeight() == 0) {
            return;
        }

        Bitmap bitmap = mWeakBitmap == null ? null : mWeakBitmap.get();
        if (bitmap == null || bitmap.isRecycled()) {
            bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
            mWeakBitmap = new WeakReference<Bitmap>(bitmap);
        }

        Canvas drawCanvas = mWeakCanvas == null ? null : mWeakCanvas.get();
        if (drawCanvas == null) {
            drawCanvas = new Canvas(bitmap);
            mWeakCanvas = new WeakReference<Canvas>(drawCanvas);
        }

        float scale = 1.0f;
        int drawableWidth = drawable.getIntrinsicWidth();
        int drawableHeight = drawable.getIntrinsicHeight();

        scale = getWidth() * 1.0f / Math.min(drawableWidth, drawableHeight);
        drawable.setBounds(0, 0, (int) (scale * drawableWidth), (int) (scale * drawableHeight));
        drawable.draw(drawCanvas);

        mPaint.reset();
        mPaint.setFilterBitmap(false);
        mPaint.setXfermode(mXfermode);

        Bitmap maskBitmap = mMaskWeakBitmap == null ? null : mMaskWeakBitmap.get();
        if (maskBitmap == null || maskBitmap.isRecycled()) {
            maskBitmap = getMaskBitmap();
            mMaskWeakBitmap = new WeakReference<Bitmap>(maskBitmap);
        }
        drawCanvas.drawBitmap(maskBitmap, 0, 0, mPaint);
        mPaint.setXfermode(null);
        if (mBorderWidth > 0) {
            drawCircleBorder(drawCanvas);
        }
        if (mIsVip == IS_VIP && (mSmallImageWidth > 0 || mSmallImageHeight > 0)) {
            drawSmallIcon(drawCanvas);
        }

        canvas.drawBitmap(bitmap, 0, 0, null);
    }


    private Bitmap getMaskBitmap() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        canvas.drawCircle(getWidth() / 2, getWidth() / 2, getWidth() / 2 - mBorderWidth, paint);

        return bitmap;
    }

    private void drawCircleBorder(Canvas canvas) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setDither(true);
        paint.setColor(mBorderColor);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(mBorderWidth);
        canvas.drawCircle(getWidth() / 2, getWidth() / 2, (getWidth() - mBorderWidth) / 2, paint);
    }

    private void drawSmallIcon(Canvas canvas) {
        int smallIconSize = mSmallImageWidth;
        Bitmap smallIconBitmap = BitmapFactory.decodeResource(getResources(), mSmallIconResId);
        smallIconBitmap = scaleImage(smallIconBitmap, smallIconSize, smallIconSize);
        float marginTop = getWidth() / 2.0f   (float)Math.sqrt(2) * (getHeight() / 2.0f) / 2.0f
                - smallIconSize / 2.0f;
        float marginLeft = marginTop;
        canvas.drawBitmap(smallIconBitmap, marginLeft, marginTop, null);
        smallIconBitmap.recycle();
    }

    private Bitmap scaleImage(Bitmap bitmap, float newWidth, float newHeight) {
        float width = bitmap.getWidth();
        float height = bitmap.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = newWidth / width;
        float scaleHeight = newHeight / height;
        matrix.postScale(scaleWidth, scaleHeight);
        return Bitmap.createBitmap(bitmap, 0, 0, (int) width, (int) height, matrix, true);
    }

    public ImageView getRoundImageView() {
        return this;
    }

    public void setIsVip(int isVip) {
        if (mIsVip != isVip) {
            mIsVip = isVip;
            invalidate();
        }
    }
}

0 人点赞