自定义右上角数字圆点ImageView——NumImageView

我们经常会遇到需要在图标的右上角显示一个小红点或者包含数字的小红点,在网上搜罗了一番,然后决定自己来写一个~~

效果图如下:

可以是圆点、数字加圆点、数字加椭圆

字体大小颜色和背景大小颜色都可以调整。

源码地址:https://github.com/SkUnK-cc/MyWidgetLib

如何使用?

首先引入依赖

implementation 'com.github.wuxiaogui593:MyWidgetLib:v1.1'

然后就可以使用了

先来看看有哪些属性~

textSize是字体的大小;textMargin是字体距离背景边缘的宽度;pointColor是背景图形的颜色;textColor是字体颜色;
show决定是否展示右上角圆点和字体,当show为false时,和普通图片没区别;pointText是右上角的字;
noNumRadius是只显示圆点不显示数字的时候,圆点的半径;bgShape代表圆形还是椭圆。

也可以在代码中设置这些属性。

比如这样

noNumRadius只在pointText长度为0,也就是没文字的时候,noNumRadius才生效。

代码

继承自AppCompatImageView

public class NumImageView extends AppCompatImageView

初始化,这里有一点注意的

getDimension 、 getDimensionPixelSize 、getDimensionPixelOffset的区别

这三个方法返回的值有一个共性:如果xml中设置的值是 X px,则结果为 X ,如果xml中的值是 X dp,则结果为 X 乘屏幕密度

getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸,如果是px,则返回原数值,如果是dp,则乘以屏幕密度后返回,也就是说返回的是像素值。要注意这个函数的返回值是float。

getDimensionPixelSize()与getDimension()功能类似,不同的是将结果转换为int,并且小数部分四舍五入。

getDimensionPixelOffset()与getDimension()功能类似,不同的是将结果转换为int,并且偏移转换(offset conversion,函数命名中的offset是这个意思)是直接截断小数位,即取整(其实就是把float强制转化为int,注意不是四舍五入哦)。

private void init(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.NumImageView);
        textSize = (int) array.getDimension(R.styleable.NumImageView_textSize,30);
        ovalPadding = (int) array.getDimension(R.styleable.NumImageView_textMargin,6);
        bgColor = array.getColor(R.styleable.NumImageView_pointColor,Color.parseColor("#B71212"));
        textColor = array.getColor(R.styleable.NumImageView_textColor,Color.parseColor("#ffffff"));
        showPoint = array.getBoolean(R.styleable.NumImageView_show,false);
        text = array.getString(R.styleable.NumImageView_pointText);
        if (text ==null){
            text = "";
        }
        noNumRadius = (int) array.getDimension(R.styleable.NumImageView_noNumRadius,0);
        bgShape = array.getInteger(R.styleable.NumImageView_bgShape,-1);
    }

当text的长度为0时,只画圆点 drawCircle() ;否则,根据bgShape指定背景形状,圆形drawCircleWithText()或椭圆drawOvalWithText();如果没有指定bgShape,则当text长度为1时,形状为圆形,大于1时,形状为椭圆。

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(!showPoint)return;
        initPaint();
        if(text.length()==0){
            // 当text 长度为0时,只画 圆形背景
            drawCircle(canvas);
            return;
        }
        if (bgShape == 0){
            // 指定背景图形为圆形
            drawCircleWithText(canvas);
        }else if (bgShape == 1){
            // 指定背景图形为椭圆
            drawOvalWithText(canvas);
        }else{
            // 没有指定 bgShape
            if(text.length()==1) {
                // text长度为1 ,画圆
                drawCircleWithText(canvas);
            }else{
                // text长度大于1,画椭圆
                drawOvalWithText(canvas);
            }
        }
    }

核心部分就是drawCircle() 、drawCircleWithText()、drawOvalWithText()三个方法;

drawCircle()

如果没有指定noNumRadius,则默认以图片的五分之一作为半径。

/**
     * 只画圆点
     */
private void drawCircle(Canvas canvas) {
        bgPaint.setColor(bgColor);
        bgPaint.setStyle(Paint.Style.FILL);
        width = getMeasuredWidth();
        // 小圆点半径占控件宽度的比例
        if(noNumRadius!=0){
            radius = noNumRadius;
        }else {
            radius = width / 5;
        }
        // 根据半径选择圆点中心点的位置
        cx = width-radius;
        cy = radius;
        canvas.drawCircle(cx,cy,radius, bgPaint);
    }

drawCircleWithText()

    /**
     * 画带文字的圆
     */
    private void drawCircleWithText(Canvas canvas) {
        bgPaint.setColor(bgColor);
        bgPaint.setStyle(Paint.Style.FILL);
        textPaint.getTextBounds(text,0, text.length(),textRect);
        width = getMeasuredWidth();

        radius = textRect.width()/2 + ovalPadding;

        // 根据半径选择圆点中心点的位置
        cx = width-radius;
        cy = radius;
        canvas.drawCircle(cx,cy,radius, bgPaint);

        textPaint.setTextAlign(Paint.Align.CENTER);
        baseY = (int) ((radius) - ((textPaint.descent() + textPaint.ascent()) / 2));
        canvas.drawText(text, cx, baseY, textPaint);
    }

drawOvalWithText() 

/**
     * 画带文字的椭圆
     */
    private void drawOvalWithText(Canvas canvas) {
        textPaint.getTextBounds(text,0, text.length(),textRect);
        width = getMeasuredWidth();
        // Right留出 高度的一半来画弧线
        ovalRight = width - textRect.height()/2;
        ovalLeft = (int) (ovalRight - textRect.width());
        ovalTop = 0;
        ovalBottom = ovalTop + textRect.height() + ovalPadding*2;

        bgPath.addArc(new RectF(ovalLeft-textRect.height()/2,ovalTop,ovalLeft+textRect.height()/2,ovalBottom),90,180);
        bgPath.lineTo(ovalRight,ovalTop);
        bgPath.addArc(new RectF(ovalRight-textRect.height()/2,ovalTop,ovalRight+textRect.height()/2,ovalBottom),270,180);
        bgPath.lineTo(ovalLeft,ovalBottom);

        bgPaint.setColor(bgColor);
        bgPaint.setStyle(Paint.Style.FILL);
        canvas.drawPath(bgPath, bgPaint);

        // Paint.Align.LEFT 代表文本被画在中点的 右边
        textPaint.setTextAlign(Paint.Align.LEFT);
        canvas.drawText(text + "", ovalLeft, textRect.height()+ovalPadding, textPaint);
    }

 

文章到此结束

喜欢点个赞~~

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值