Android 小红点 未读消息功能 BadgeHelper
因为最近的项目需求,翻遍github上的未读消息红点开源库, 发现大部分
不能适配不同情况的布局, 所以我写了一个能兼容全部的 !
网上的写法是 继承TextView然后生成一个小红点drawable,设置到背景中去, 然后把目标view外层加一层FrameLayout,然后把小红点添加进去
但这样做的问题来了, 小红点与目标View 会叠起来!, 挡住文字,!!! 看得我瞎了~~~ 而且 他们提供的setOffsetX setpadding 之类的没卵用,你如果想要偏移小红点让它不与下面的View重叠,那是不可能的
所以我的写法是 为了更好的性能,直接继承View然后画小红点背景, 然后把目标view外层加一层LinearLayout 让小红点View放目标的右边,这样就不会重叠
同时 我也支持设置 重叠模式和非重叠模式
这是效果图
由于github账号出问题了,没法上传, 所以写到博客上算了
这只是一个小工具类 供大家学习下我的思路, 就不多说了, 具体实现注释里写的很清楚,不太清楚的可以回复问我
#核心类:
##BadgeHelper .java
package com.truescend.gofit.views;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.IntDef;
import android.support.design.widget.TabLayout;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
/**
* 作者:东芝(2018/8/23).
* 支持 重叠目标模式 和 放目标右上角但不重叠的模式 两种模式 通过setOverlap 设置, 默认为false=不重叠
*/
public class BadgeHelper extends View {
private static final String TAG = "BadgeHelper";
private float density;
private Paint mTextPaint;
private Paint mBackgroundPaint;
private String text = "0";
private int number;
@Type
private int type = Type.TYPE_POINT;
private boolean isOverlap;
private final RectF rect = new RectF();
private int badgeColor = 0xFFD3321B; //默认的小红点颜色
private int textColor = 0xFFFFFFff;
private float textSize;
private int w;
private int h;
private boolean isSetup;
private boolean mIgnoreTargetPadding;
private boolean isCenterVertical;
private int leftMargin;
private int topMargin;
private int rightMargin;
private int bottomMargin;
@IntDef({
Type.TYPE_POINT, Type.TYPE_TEXT})
@Retention(RetentionPolicy.SOURCE)
public @interface Type {
int TYPE_POINT = 0;
int TYPE_TEXT = 1;
}
public BadgeHelper(Context context) {
super(context);
}
private void init(@Type int type, boolean isOverlap) {
this.type = type;
this.isOverlap = isOverlap;
density = getResources().getDisplayMetrics().density;
switch (type) {
case Type.TYPE_POINT:
mBackgroundPaint = new Paint();
mBackgroundPaint.setStyle(Paint.Style.FILL);
mBackgroundPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(badgeColor);
//计算小红点无文本情况下的小红点大小, 按屏幕像素计算, 如果你有你自己认为更好的算法, 改这里即可
w = h = Math.round(density * 7f);
break;
case Type.TYPE_TEXT:
mBackgroundPaint = new Paint();
mBackgroundPaint.setStyle(Paint.Style.FILL);
mBackgroundPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setColor(badgeColor);
mTextPaint = new Paint();
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(textColor);//文本颜色
if (textSize == 0) {
mTextPaint.setTextSize(density * 10);//文本大小按屏幕像素 计算, 没写死是为了适配各种屏幕, 但如果你有你认为更合理的计算方式 你可以改这里
} else {
mTextPaint.setTextSize(textSize);//使用自定义大小
}
//计算小红点有文本情况下的小红点大小, 按文本宽高计算, 如果你有你自己认为更好的算法, 改这里即可
float textWidth = getTextWidth("99", mTextPaint);
w = h = Math.round(textWidth * 1.4f);//让背景比文本大一点
break;
}
}
/**
* 设置Margin 可用于做偏移
* @param left
* @param top
* @param right
* @param bottom
* @return
*/
public BadgeHelper setBadgeMargins(int left, int top, int right, int bottom) {
leftMargin = left;
topMargin = top;
rightMargin = right;
bottomMargin = bottom;
return this;