美文网首页
仿钉钉头像(有头像显示图片拼接,无图显示昵称)

仿钉钉头像(有头像显示图片拼接,无图显示昵称)

作者: BKQ_SYC | 来源:发表于2018-12-14 10:06 被阅读49次

    一、需求

      1. 多图拼接展示(目前最多支持四张图)
      2. 可展示文字
      3. 可展示成圆角、方角、圆形
      4. 可自定义分割线宽度、颜色
      5. 可设置是否包含边框
    

    二、预览

    预览图.jpg

    三、代码

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.PorterDuff;
    import android.graphics.PorterDuffXfermode;
    import android.graphics.RectF;
    import android.support.v4.content.ContextCompat;
    
    import java.util.List;
    
    /**
     * Describe : https://github.com/NFLeo
     * Created by Leo on 2018/12/13 on 13:57.
     */
    class AvatarUtil {
    
        static Builder getBuilder(Context context) {
            return new Builder(context);
        }
    
        public static class Builder {
    
            private Context mContext;
            private List<Object> mList;                      // 数据源
            private int mWidth = 50;                         // 控件宽度
            private int mHeight = 50;                        // 控件高度
    
            private int mShape = Shape.CIRCLE;               // 控件形状
            private int mRoundAngel = 10;                    // 圆角大小
            private int mMarginWidth = 4;                    // 图片间隙
            private int mMarginColor = R.color.gray;         // 图片间隙颜色
            private boolean hasEdge = true;                  // 是否包含边缘
    
            private float mTextSize = 50;                           // 文字大小
            private int mTextColor = R.color.colorPrimary;          // 文字颜色
            private int mBackGroundColor = R.color.colorAccent;     // 文字背景颜色
    
            private Builder(Context context) {
                this.mContext = context;
            }
    
            /**
             * 设置数据源
             */
            Builder setList(List<Object> mList) {
                this.mList = mList;
                return this;
            }
    
            /**
             * 设置图片尺寸
             */
            Builder setBitmapSize(int mWidth, int mHeight) {
                if (mWidth > 0) {
                    this.mWidth = mWidth;
                }
    
                if (mHeight > 0) {
                    this.mHeight = mHeight;
                }
                return this;
            }
    
            /**
             * 设置展示类型(圆形、圆角、方形)
             */
            Builder setShape(int mShape) {
                this.mShape = mShape;
                return this;
            }
    
            /**
             * 设置圆角角度
             * 当shape设置为Shape.Round时读取改属性
             *
             * @param mRoundAngel 圆角角度
             */
            Builder setRoundAngel(int mRoundAngel) {
                this.mRoundAngel = mRoundAngel;
                return this;
            }
    
            /**
             * 设置分割线宽度
             */
            Builder setMarginWidth(int mMarginWidth) {
                this.mMarginWidth = mMarginWidth;
                return this;
            }
    
            /**
             * 设置分割线颜色
             */
            public Builder setMarginColor(int mMarginColor) {
                this.mMarginColor = mMarginColor;
                return this;
            }
    
            /**
             * 设置文字大小
             */
            public Builder setTextSize(int mTextSize) {
                this.mTextSize = mTextSize;
                return this;
            }
    
            /**
             * 设置文字颜色
             */
            public Builder setTextColor(int mTextColor) {
                this.mTextColor = mTextColor;
                return this;
            }
    
            public Builder setHasEdge(boolean hasEdge) {
                this.hasEdge = hasEdge;
                return this;
            }
    
            Bitmap create() {
    
                final Bitmap result = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
                Canvas canvas = new Canvas(result);
    
                Paint paint = new Paint();
                paint.setAntiAlias(true);
                canvas.drawPath(drawShapePath(), paint);
                float[] marginPath;
    
                final int listSize = mList.size();
                switch (listSize) {
                    case 1:
                        startDraw(canvas, mList.get(0), DrawPosition.WHOLE);
                        break;
                    case 2:
                        startDraw(canvas, mList.get(0), DrawPosition.LEFT);
                        startDraw(canvas, mList.get(1), DrawPosition.RIGHT);
                        marginPath = new float[]{mWidth / 2, 0, mWidth / 2, mHeight};
                        drawMarginLine(canvas, marginPath);
                        break;
                    case 3:
                        startDraw(canvas, mList.get(0), DrawPosition.LEFT);
                        startDraw(canvas, mList.get(1), DrawPosition.RIGHT_TOP);
                        startDraw(canvas, mList.get(2), DrawPosition.RIGHT_BOTTOM);
                        marginPath = new float[]{mWidth / 2, 0,
                                mWidth / 2, mHeight,
                                mWidth / 2, mHeight / 2,
                                mWidth, mHeight / 2};
                        drawMarginLine(canvas, marginPath);
                        break;
                    default:
                        startDraw(canvas, mList.get(0), DrawPosition.LEFT_TOP);
                        startDraw(canvas, mList.get(1), DrawPosition.LEFT_BOTTOM);
                        startDraw(canvas, mList.get(2), DrawPosition.RIGHT_TOP);
                        startDraw(canvas, mList.get(3), DrawPosition.RIGHT_BOTTOM);
                        marginPath = new float[]{mWidth / 2, 0,
                                mWidth / 2, mHeight,
                                0, mHeight / 2,
                                mWidth, mHeight / 2};
                        drawMarginLine(canvas, marginPath);
                        break;
                }
                // 仅方形支持边缘  且单个文字不支持边缘
                if (hasEdge && mShape == Shape.SQUARE && !(mList.size() == 1 && mList.get(0) instanceof String)) {
                    drawEdge(canvas);
                }
    
                return result;
            }
    
            /**
             * 根据边角配置绘制画布path
             */
            private Path drawShapePath() {
                Path mPath = new Path();
                switch (mShape) {
                    case Shape.ROUND:
                        mPath.addRoundRect(new RectF(0, 0, mHeight, mWidth), mRoundAngel, mRoundAngel, Path.Direction.CCW);
                        break;
                    case Shape.SQUARE:
                        mPath.addRect(new RectF(0, 0, mHeight, mWidth), Path.Direction.CCW);
                        break;
                    case Shape.CIRCLE:
                        int radius = Math.max(mWidth, mHeight) / 2;
                        mPath.addCircle(mWidth / 2, mHeight / 2, radius, Path.Direction.CCW);
                        break;
                }
    
                return mPath;
            }
    
            /**
             * 根据数据源类型区分绘制图片或文字
             */
            private void startDraw(Canvas canvas, Object resource, int position) {
                if (resource instanceof Bitmap) {
                    drawBitmap(canvas, (Bitmap) resource, position);
                } else if (resource instanceof String) {
                    drawText(canvas, (String) resource, position);
                }
            }
    
            /**
             * 绘制图片
             * 最多支持四张图
             */
            private void drawBitmap(Canvas canvas, Bitmap bitmap, int mode) {
    
                int left, top;
                int x, y, width, height;
                int dstWidth, dstHeight;
    
                Paint paint = new Paint();
                paint.setAntiAlias(true);
                paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    
                if (mode == DrawPosition.WHOLE) {
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, mWidth, mHeight, false);
                    canvas.drawBitmap(bmp, 0, 0, paint);
                } else if (mode == DrawPosition.LEFT) {
                    dstWidth = mWidth;
                    dstHeight = mHeight;
    
                    x = mWidth / 4 + mMarginWidth / 4;
                    y = 0;
                    width = mWidth / 2 - mMarginWidth / 4;
                    height = mHeight;
    
                    left = 0;
                    top = 0;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 裁取中间部分(从x点裁取置顶距离)
                    Bitmap dstBmp = Bitmap.createBitmap(bmp, x, y, width, height);
                    // 绘图
                    canvas.drawBitmap(dstBmp, left, top, paint);
                } else if (mode == DrawPosition.RIGHT) {
                    dstWidth = mWidth;
                    dstHeight = mHeight;
    
                    x = mWidth / 4 + mMarginWidth / 4;
                    y = 0;
                    width = mWidth / 2 - mMarginWidth / 4;
                    height = mHeight;
    
                    left = mWidth / 2 + mMarginWidth / 4;
                    top = 0;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 裁取中间部分(从x点裁取置顶距离)
                    Bitmap dstBmp = Bitmap.createBitmap(bmp, x, y, width, height);
                    // 绘图
                    canvas.drawBitmap(dstBmp, left, top, paint);
                } else if (mode == DrawPosition.LEFT_TOP) {
                    dstWidth = mWidth / 2 - mMarginWidth / 4;
                    dstHeight = mHeight / 2 - mMarginWidth / 4;
    
                    left = 0;
                    top = 0;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 绘图
                    canvas.drawBitmap(bmp, left, top, paint);
                } else if (mode == DrawPosition.LEFT_BOTTOM) {
                    dstWidth = mWidth / 2 - mMarginWidth / 4;
                    dstHeight = mHeight / 2 - mMarginWidth / 4;
    
                    left = 0;
                    top = mHeight / 2 + mMarginWidth / 4;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 绘图
                    canvas.drawBitmap(bmp, left, top, paint);
                } else if (mode == DrawPosition.RIGHT_TOP) {
                    dstWidth = mWidth / 2 - mMarginWidth / 4;
                    dstHeight = mHeight / 2 - mMarginWidth / 4;
    
                    left = mWidth / 2 + mMarginWidth / 4;
                    top = 0;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 绘图
                    canvas.drawBitmap(bmp, left, top, paint);
                } else if (mode == DrawPosition.RIGHT_BOTTOM) {
                    dstWidth = mWidth / 2 - mMarginWidth / 4;
                    dstHeight = mHeight / 2 - mMarginWidth / 4;
    
                    left = mWidth / 2 + mMarginWidth / 4;
                    top = mHeight / 2 + mMarginWidth / 4;
    
                    // 比例缩放
                    Bitmap bmp = Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, false);
                    // 绘图
                    canvas.drawBitmap(bmp, left, top, paint);
                }
            }
    
            /**
             * 绘制文字
             */
            private void drawText(Canvas canvas, String text, int mode) {
                float bgLeft = 0, bgTop = 0, bgRight = 0, bgBottom = 0;
                float textSize = mTextSize;
    
                Paint textBgPaint = new Paint();
                textBgPaint.setColor(ContextCompat.getColor(mContext, mBackGroundColor));
                textBgPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
                if (mode == DrawPosition.WHOLE) {
                    bgLeft = 0;
                    bgTop = 0;
                    bgRight = mWidth;
                    bgBottom = mHeight;
                    textSize = mWidth / 2;
                } else if (mode == DrawPosition.LEFT) {
                    bgLeft = 0;
                    bgTop = 0;
                    bgRight = mWidth / 2 - mMarginWidth / 4;
                    bgBottom = mHeight;
                    textSize = mWidth / 4;
                } else if (mode == DrawPosition.RIGHT) {
                    bgLeft = mWidth / 2 + mMarginWidth / 4;
                    bgTop = 0;
                    bgRight = mWidth;
                    bgBottom = mHeight;
                    textSize = mWidth / 4;
                } else if (mode == DrawPosition.LEFT_TOP) {
                    bgLeft = 0;
                    bgTop = 0;
                    bgRight = mWidth / 2 - mMarginWidth/ 4;
                    bgBottom = mHeight / 2 - mMarginWidth/ 4;
                    textSize = mWidth / 5;
                } else if (mode == DrawPosition.LEFT_BOTTOM) {
                    bgLeft = 0;
                    bgTop = mHeight / 2 + mMarginWidth/ 4;
                    bgRight = mWidth / 2 - mMarginWidth/ 4;
                    bgBottom = mHeight;
                    textSize = mWidth / 5;
                } else if (mode == DrawPosition.RIGHT_TOP) {
                    bgLeft = mWidth / 2 + mMarginWidth/ 4;
                    bgTop = 0;
                    bgRight = mWidth;
                    bgBottom = mHeight / 2 - mMarginWidth/ 4;
                    textSize = mWidth / 5;
                } else if (mode == DrawPosition.RIGHT_BOTTOM) {
                    bgLeft = mWidth / 2 + mMarginWidth/ 4;
                    bgTop = mHeight / 2 + mMarginWidth/ 4;
                    bgRight = mWidth;
                    bgBottom = mHeight;
                    textSize = mWidth / 5;
                }
    
                RectF rect = new RectF(bgLeft, bgTop, bgRight, bgBottom);
                canvas.drawRect(rect, textBgPaint);
    
                Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
                textPaint.setAntiAlias(true);
                textPaint.setColor(ContextCompat.getColor(mContext, mTextColor));
                textPaint.setTextSize(Math.min(mTextSize, textSize));
    
                textPaint.setStyle(Paint.Style.FILL);
                textPaint.setTextAlign(Paint.Align.CENTER);
                Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
    
                int baseline = (int) ((bgBottom + bgTop - fontMetrics.bottom - fontMetrics.top) / 2);
                canvas.drawText(text, rect.centerX(), baseline, textPaint);
            }
    
            /**
             * 绘制边缘线
             */
            private void drawEdge(Canvas canvas) {
                Paint edgePaint = new Paint();
                edgePaint.setStrokeWidth(mMarginWidth);
                edgePaint.setStyle(Paint.Style.STROKE);
                edgePaint.setColor(ContextCompat.getColor(mContext, mMarginColor));
    
                Path mPath = new Path();
                mPath.moveTo(0, 0);
                mPath.lineTo(0, mHeight);
                mPath.lineTo(mWidth, mHeight);
                mPath.lineTo(mWidth, 0);
                mPath.close();
    
                canvas.drawPath(mPath, edgePaint);
            }
    
            /**
             * 绘制分割线
             */
            private void drawMarginLine(Canvas canvas, float[] path) {
                Paint marginPaint = new Paint();
                marginPaint.setStrokeWidth(mMarginWidth / 2);
                marginPaint.setColor(ContextCompat.getColor(mContext, mMarginColor));
                canvas.drawLines(path, marginPaint);
            }
        }
    
        public interface Shape {
            int ROUND = 0X33;
            int CIRCLE = 0X11;
            int SQUARE = 0X22;
        }
    
        interface DrawPosition {
            int WHOLE = 0;
            int LEFT = 1;
            int RIGHT = 2;
            int LEFT_TOP = 3;
            int LEFT_BOTTOM = 4;
            int RIGHT_TOP = 5;
            int RIGHT_BOTTOM = 6;
        }
    }
    
    

    四、使用

    1. 复制该类到项目
    2. 调用以下方法
    
    // 注:目标图转换成Bitmap,多Bitmap拼接都放在子线程操作
    List<Object> bitmapList = new ArrayList()
    bitmapList.add(bitmap)         // 添加图片转换完成的bitmap
    bitmapList.add("钱")           // 可添加需展示的文字
    
    Bitmap avatar = AvatarUtil.getBuilder(AvatarActivity.this)
                            .setShape(shape)
                            .setMarginWidth(width)
                            .setRoundAngel(height)
                            .setList(bitmapList)
                            .setTextSize(textSize)            // px
                            .setTextColor(R.color.black)      // 需传入color文件下的颜色值
                            .setBitmapSize(size, size)
                            .setHasEdge(hasEdge)
                            .create();
    
    // 放到主线程
    ivAvatar.setImageBitmap(avatar)
    
    可以用rxjava线程切换
    

    五、说明

    注:
       1. 拼接最多支持四张,需要更多可自行计算
       2. 尺寸传值(图片尺寸、文字尺寸、间隔尺寸),需外部计算成px
       3. 颜色传值,需传入color文件中的色值,例如R.color.black
    

    相关文章

      网友评论

          本文标题:仿钉钉头像(有头像显示图片拼接,无图显示昵称)

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