Android中的红点提示怎么统一实现

image.png

  App中的红点广泛用于提醒功能,虽然用在菜单上、Tab上、列表,但本质它就是一个红色的View,不就是放哪里就显示在哪里嘛,有什么难的?对!这是UI设计师和产品经理的一致观点,但是作为开发你可别信了他们的鬼话!
  这边文章讲红点,绝不是讲如何设计红点的UI,而是讲在代码层面如何实现,如何快速集成到业务中。如果你听了UI设计师和产品的鬼话你可能就真的哪里需要显示红点然后就在哪里放红点view了,然后通过外部代码控制它的隐藏和显示,你会很累,要定义很多key-value来存储记录各种红点显示的条件,零零碎碎很分散,这根本不是统一的解决方案,这是典型的想到哪里做到哪里。
  我的想法是创建一个红点View,你可以将此红点View放置在任何需要的View的右上方,然后初始化告知它显示的条件,即:接收哪几类通知提醒,比如告知它显示的条件是App有版本提醒就结束了,条件满足自动就会显示,条件不满足自动隐藏。

关于此红点View的接入方式,非常简单如下:

// 红点提醒如果需要区分账户则需要设置账户,
// 比如:App升级提示无需区分账户,个人消息提醒需要区分账户
mRedDotView.setAccount(accountId);

// 设置当前红点监听的appLinks,只有收到了设置的AppLink才会触发当前红点的显示和隐藏
mRedDotView.setAppLinks("my-scheme://NewMsgAlert");

关于AppLink之前一篇文章提到过,本质就是借助scheme定义的url解析规则,不同的AppLink对应不用的响应策略。

下面我们分析下红点显示的特性:

  • 相似而不相同性:都是红点,只是不同位置的红点关注的提示内容不一样,所以更有必要定义统一规则来控制其显示和隐藏,因此我们使用AppLink来统一解析和管理,不同的红点View需要设置它所关注的AppLink,如上面接入方式所示,只要每个红点View在初始化时候指定想要关注的AppLinks即可,如果需要账户隔离则别忘记设置account:

  • 持久性:如果不点击、不查看,它会一直显示,哪怕App被杀掉再打开。因此,红点触发的条件是存储下来的,常见办法是通过SharedPreference或Database,我采用了Database方式,因为可以便捷的通过SQL检索以及数据统一管理,当红点View加载后会在onAttachedToWindow()里根据注册的AppLinks查询是否有未读的AppLinks:

public class PushMessageDbHelper extends SQLiteOpenHelper {
    
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS push_message (" +
                "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "title TEXT," +
                "sub_title TEXT," +
                "pic_url TEXT," +
                "app_link TEXT," +
                "account TEXT," +
                "update_dt TEXT," +
                "read INTEGER)");
    }

    // ... others
}

数据库表结构定义,这是一个融合了AppLink、推送标题、子标题、推送通知图片、账户ID、是否已读等信息的表定义。

@Override
protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    checkVisible();
    // ...other code
}

当view加载成功后查询之前有没有未读的AppLinks,如果有则设置红点显示。

  • 即时性:红点是否要显示既可以是view初始化过程中查询数据库得知的,也可以是即时通知的,比如推送使得红点显示:
public class RedDotView extends AppCompatImageView {
    private PushContentReceiver mContentReceiver = new PushContentReceiver() {

        @Override
        public String getAccount(@NonNull Context context) {
            return mAccount;
        }

        @Override
        public List<String> getAppLinks() {
            return mAppLinks;
        }

        @Override
        public boolean onReceive(@NonNull Context context, @NonNull AppLink appLink) {
            Log.d("DotView", "onReceive appLink: " + appLink);

            if (mAppLinks == null || mAppLinks.size() == 0) {
                return false;
            }

            boolean haveUnReadMsg = false;
            for (String item : mAppLinks) {
                if (PushMessageService.getInstance(getContext()).haveUnread(item, getAccount(context))) {
                    haveUnReadMsg = true;
                    break;
                }
            }

            setVisibility(haveUnReadMsg ? VISIBLE : GONE);
            return false;
        }
    };

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        PushContentReceiver.register(getContext(), mContentReceiver, false);
        checkVisible();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        PushContentReceiver.unregister(getContext(), mContentReceiver);
    }

    // ...others code
}

由上可见在View的onAttachedToWindow()里注册了一个监听AppLink的receiver。

需要注意的是这里的AppLink在定义的时候需要注明它是需要存储的,即overide shouldSave() 并返回true告知此AppLink收到后要存储在DB里,因为即便App杀掉再次打开还是需要显示红点的,如下案例:

public class NewMsgAlert extends AppLink {

    @Override
    public boolean isPrivate() {
        return true;
    }

    @Override
    public boolean shouldSave() {
        return true;
    }
}

  总之,思路并不复杂,主要是充分发挥scheme设计的AppLink带来的好处,关于此View的实现也很简单,可以参考[这里](https://github.com/daydream123/applink/blob/master/library/src/main/java/com/feizhang/applink/RedDotView.java

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342