android中的红点数字标记太普遍了,只要涉及到消息的地方都会用到。
这里介绍两种方式 简单快捷的实现其效果。
以下是效果图:
shape资源想必都会使用,这里直接给代码:
//circle_tx.xml
<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>
实现的最终效果如上图第一个控件
<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" />
实现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的效果时尤其重要,比如点击某段文字实现超链接/打电话/发短信/发邮件等等。
通过自定义的形式制作也十分简单。简单罗列下思路:
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
做一个控件除了能实现功能外,我还想使用方便,何时何地想用就用。
//以下参考网络资料实现
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号效果,红点数字不仅在右上角 还会有一定的挤出浮动效果。这里需要借助布局文件来实现了。拿第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