制作android中的红点数字提醒

android中的红点数字标记太普遍了,只要涉及到消息的地方都会用到。
这里介绍两种方式 简单快捷的实现其效果。
以下是效果图:
这里写图片描述

一.通过shape资源制作
1.1制作圆形红色背景

shape资源想必都会使用,这里直接给代码:

//circle_tx.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="30dp"
    android:width="30dp"/>
    <corners android:radius="30dp"/>
    <stroke android:width="2dp"
        android:color="#00ff00"/>
    <solid android:color="#ff0000"/>
</shape>
1.2 将shape作为textView的背景

实现的最终效果如上图第一个控件

 <!-- 使用shape资源 和重写textView 的setText方法实现红点标记 -->
    <com.example.ndh.redlabelview.RedLabelTextView
        android:textColor="@android:color/white"
        android:gravity="center"
        //这里将shape资源作为textView的圆形背景
        android:background="@drawable/circle_tx"
        android:text="1000"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
1.3 实现99+的效果

实现99+的时候为了让“+”上标显示,这里需要自定义一个textView,复写setText方法。

@Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
        String destStr="";
       int num= Integer.parseInt(text+"");
        if(num<=0){
            num=0;
        }
        //数字大于99 就以99+的形式展示
        if(num>99){
         destStr="99+";
            SpannableString spannableString=new SpannableString(destStr);
            //将+用作上标显示
            spannableString.setSpan(new SuperscriptSpan(),2,3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            super.setText(spannableString,type);
        }else{
            super.setText(num+"");
        }
    }

这里的实现使用了spannableString,它是CharSequence的子类。功能特别丰富,在制作多样化textView的效果时尤其重要,比如点击某段文字实现超链接/打电话/发短信/发邮件等等。

二、自定义控件实现
2.1 绘制界面

通过自定义的形式制作也十分简单。简单罗列下思路:
1 通过canvas.drawCircle画一个红色的背景
2 通过canvas.drawText将text画到背景上
3 如果数字大于99需要画上上标的“+”

@Override
    protected void onDraw(Canvas canvas) {
        Log.d("ndh--","onDraw--");
        paint.setColor(bgColor);
        paint.setAlpha(225);
        paint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.SOLID) );
        //画红色背景
        canvas.drawCircle(getMeasuredWidth() / 2, getMeasuredHeight() / 2, r, paint);
//        paint.setMaskFilter(null);
        //这两个矩形分别是为了定位text和+的位置的
        Rect rect = new Rect(getMeasuredWidth() / 2 - r, getMeasuredHeight() / 2 - r, getMeasuredWidth() / 2 + r, getMeasuredHeight() / 2 + r);//画一个矩形
        Rect rect1 = new Rect(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - r, getMeasuredWidth() / 2 + r, getMeasuredHeight() / 2);//画一个矩形

        if (Integer.parseInt(mText) < 0) {
            mText = "0";
        }
        //数字小于99 直接将其画到面板上
        if (Integer.parseInt(mText) <= 99) {
            paint.setTextSize(r);
            drawStr(canvas, paint, rect, false);
        } else {
        //如果数字大于99 则还需要画上右标的“+”
            paint.setTextSize(r);
            drawStr(canvas, paint, rect, true);
            paint.setColor(textColor);
            float x1 = getMeasuredWidth() / 2 + r / 2;
            float y1 = (rect1.bottom + rect1.top - paint.getFontMetrics().bottom - paint.getFontMetrics().top) / 2;
            canvas.drawText("+", x1, y1, paint);
        }

注意:我们需要将文字画到红色圆的正中间,canvas在画文字的时候比较特别,它的绘制标杆是x为中轴,y为基线进行的绘制,因此为了让字体正中间显示,需要调整基线。参考:http://blog.csdn.net/zly921112/article/details/50401976

2.2 将控件作用到任意view的右上角

做一个控件除了能实现功能外,我还想使用方便,何时何地想用就用。

//以下参考网络资料实现
public void setTargetView(View target) {
//获取目标控件的父容器
        ViewGroup parentContainer = (ViewGroup) target.getParent();
        int index = parentContainer.indexOfChild(target);
        parentContainer.removeView(target);
        //定义一个framelayout,准备将目标view和自定义控件包裹到一起
        FrameLayout badgeContainer = new FrameLayout(getContext());
        ViewGroup.LayoutParams parentLayoutParams = target.getLayoutParams();
//        badgeContainer.setPadding(0,200,200,0);
        badgeContainer.setLayoutParams(parentLayoutParams);
        target.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        badgeContainer.addView(target);
        FrameLayout.LayoutParams fl = new FrameLayout.LayoutParams(parentLayoutParams);
        //让自定义控件摆放到父控件的右上角
        fl.gravity = Gravity.TOP | Gravity.RIGHT;
        badgeContainer.addView(this, fl);
        parentContainer.addView(badgeContainer, index, parentLayoutParams);
        postInvalidate();
    }

在使用的时候异常简单:

 RelativeLayout relativeLayout2 = (RelativeLayout)   findViewById(R.id.rl2);
        RedLabel label1 = new RedLabel(this, 20);
        label1.setNum(100);
        label1.setTargetView(relativeLayout2);

如上几句代码已经实现将红点数字摆放到任意view的右上角,并且不会影响到目标view的原始布局,不会发生任何界面形变,最终效果如上图的4,5,6号效果。

2.3 控件右上角挤出效果

为了实现2,3号效果,红点数字不仅在右上角 还会有一定的挤出浮动效果。这里需要借助布局文件来实现了。拿第3号的button效果举例:
对应的布局文件如下:

<RelativeLayout
    android:id="@+id/rl"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
    <Button
    //button离父控件有一定距离
        android:layout_margin="10dp"
        android:background="@drawable/bg_bt"
        android:id="@+id/bt"
        android:text="button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>

然后在代码中使用的时候,将红点数字的自定义view不是直接加到button上,而是加到其外层父控件RelativeLayout上:

RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rl);
 RedLabel label2 = new RedLabel(this, 30);
        label2.setNum(20);
        label2.setTargetView(relativeLayout);

还记得上面button的布局文件中留的margin吗,调整这个属性就可以调整数字红点在button右上角的挤出范围。

三、事例代码

代码见github:https://github.com/killer8000/RedLabelView

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值