Code Monkey home page Code Monkey logo

rjbadgekit's Introduction

RJBadgeKit

CI Status Version License Platform

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Installation

RJBadgeKit is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'RJBadgeKit'

Introduction

This is the code repository associated with blog article: https://juejin.im/post/5b80265de51d4538a31b4165

RJBadgeKit是一套完整的小红点(消息推送提示)解决方案,使用场景为App某个功能块有内容更新或有未读消息时右上角会有小红点提示。RJBadgeKit支持小红点数字显示两种形式,小红点也可以是自定义图片。 另外,提供多层级小红点的关联显示逻辑,比如微信tab上的小红点显示数字为聊天列表里未读消息的总和,只有所有未读消息都清空的情况下tab上的小红点才会消失。

image

RJBadgeKit的小红点所支持的路径格式为root.xx.xx, 小红点原则是父节点的小红点为子节点的小红点并集。root为默认的根路径。如下图所示,root.first为子路径,root.second为同级子路径。在纯红点模式下,root的小红点显示为root.first, root.second和root.third的并集,同理在数字显示模式下,root的badge数量为root.first, root.second和root.third的badge数量之和。而root.first的badge数量则又为root.first.firstA和root.first.firstB的和。

image

Useage

RJBadgeKit的用法包括a) add observer b) set/clear badge c) show/hide badge, 接口分别如下所示:

Add observer

假设我们有个促销页面,该促销有两个商品参与活动,则促销页面的路径可设置为root.promotion,促销页面内两个商品的路径分别设为root.promotion.item1, root.promotion.item2. 现在需要推送小红点消息给用户,在promotion的入口处的button需要显示小红点提示,当用户进入到promotion页面且分别点击了item1和item2后,promotion的小红点提示才消失。

首先我们在RJPromotionViewController里面对promotionButton添加路径的观察者,当该路径被set badge时候则显示小红点,clear badge时则隐藏小红点:

[self.badgeController observePath:@"root.promotion" 
                        badgeView:promotionButton 
                            block:^(RJPromotionViewController *observer, NSDictionary *info) {
    // Use [observer doSomething] instead of [self doSomething] to avoid retain cycle in block
    // key path     -> info[RJBadgePathKey] : badgeContoller所observe的路径
    // badge status -> info[RJBadgeShowKey] : 当前路径所对应的badge是否处于set状态(是否应该显示小红点)
    // badge count  -> info[RJBadgeCountKey]: 当前路径所对应的badge数值(仅在badge为数值模式下有效)
}];

这里需要注意的几点是:

  1. self.badgeController为动态生成的属性,无需自己定义和初始化,RJBadgeKit为所有NSObject对象通过category添加了badgeController
  2. 无需调用remove observer, RJBadgeKit通过自释放机制自动移除observer. 如果确实需要提前移除观察者,可以调用unobservePath接口
  3. 为防止循环引用,在badge的block里面用参数observer来代替self, RJBadgeKit对observer(即self.badgeController的self)进行了weak化处理并通过block回调参数传出

Set/clear badge

在上述例子中,当网络请求返回时发现有两个促销数据,则调用:

[RJBadgeController setBadgeForKeyPath:@"root.promotion.item1"];
[RJBadgeController setBadgeForKeyPath:@"root.promotion.item2"];

子节点的badge状态变化会触发父节点observe的block回调,所以上述两行代码执行后promotionButton会触发显示小红点。当然如果希望promotionButton不显示小红点,而是显示具体的促销数量,则可以直接如下调用:

[RJBadgeController setBadgeForKeyPath:@"root.promotion" count:2];

如果promotion item下面还有子节点, 则调用:

[RJBadgeController setBadgeForKeyPath:@"root.promotion.item1" count:5];

在这个情况下,promotionButton上显示的数值(亦即root.promotion路径对应的badge值)为root.promotion.item1和root.promotion.item2及其所有子节点的数值之和。当用户点击查看item1和item2后,分别调用clear badeg接口:

[RJBadgeController clearBadgeForKeyPath:@"root.promotion.item1"];
[RJBadgeController clearBadgeForKeyPath:@"root.promotion.item2"];

这时父节点root.promotion的badge自动clear, promotionButton的小红点会自动隐藏。如果希望在item1被clear后就强制清除root.promotion的badge, 则可以在clear item1后调用:

[RJBadgeController clearBadgeForKeyPath:@"root.promotion" force:YES];

这样即使子节点的badge尚未全部清除,父节点也会被强制clear. P.S 正常情况下不应该去调用force:YES, 如果非要调用,可能是路径结构设计不合理了。

Show/hide badge

RJBadgeKit支持UIView, UITabBarItem和UIBarButtonItem的小红点显示。小红点类型则支持默认圆形小红点,数值和自定义view/图片。显示的优先级为number > custom view > red dot

promotionButton.badgeOffset = CGPointMake(-50, 0); // 调整小红点的显示位置offset, 相对于右上角

[self.promotionButton setBadgeImage:[UIImage imageNamed:@"badgeNew"]]; // 显示自定义的badge icon

[self.promotionButton setCustomView:self.customBadgeView]; // 显示自定义的badge view

更详细的使用示例请参考RJBadgeKit的Example工程

Author

Ryan Jin, [email protected]

License

RJBadgeKit is available under the MIT license. See the LICENSE file for more info.

rjbadgekit's People

Contributors

rjinxx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rjbadgekit's Issues

How to hide badge on default

It always shows badge on default even without calling setBadgeForKeyPath, is it possible to hide badge on default?

小红点在navigationBar上点击效果的问题

我设置小红点在viewController.navigationItem.rightBarButtonItem上,显示是OK的,但是点击时候如果push到下个界面,小红点的一半就消失了。

下图为app导航栏(系统自带导航栏),当该界面push到下个vc的时候,小红点的一半就消失了,请问如何解决?

image

root 路径下可以不显示 子节点 count之和吗

root节点 - root.miniLV.page

两个子节点
NSString * const RJItemPath1 = @"root.miniLV.page.item1";
NSString * const RJItemPath2 = @"root.miniLV.page.item2";

root 节点,只想显示默认的红点状态,[RJBadgeController setBadgeForKeyPath:path count:1];即便我在 Root 上设置,count 始终 == 1,或者 == 0,计算的法则都是 RJItemPath1.count + RJItemPath2.count,有办法让 root节点如果有值默认只显示一个小红点吗

  • 目前Root中的代码,不管是[RJBadgeController setBadgeForKeyPath:path]; - 没设置count
  • 强制设置数量 - [RJBadgeController setBadgeForKeyPath:path count:0]; or [RJBadgeController setBadgeForKeyPath:path count:1];都无法实现效果

展示数字的优先级比较高,这个有办法自己控制吗

image
##需要类似这种,root层始终只显示红点(有值的情况),有办法实现吗

还有种是策略问题

实际上策略有很多种,常见数字、小红点、new

这个策略实际上是应该由使用者来提供

如果存在数字 小红点、new 哪种优先?

这样设计是否合理的问题

曾经也碰到过类似的问题, 我采用的是递归来操作,**和你差不多,但是我遇到过问题,你在这里好像也会出现

假如有这两条路径:
Root.A.a1
Root.B.b1

我现在需要新增一个需求,功能f1, 我要放在A里面,那么现在路径变为
Root.A.a1
Root.A.f1

Root.B.b1

此时运行时完美的,但是,此时会出现这么一个问题

如果产品需要把f1 放到 B里面去

而且,而且,而且
如果用户在 Root.A 里面 如果用户曾经点击过此功能, 那么就不B就没有badge,如果没有,就需要显示

理想路径变为:
Root.A.a1

Root.B.f1
Root.B.b1

但是如何计算 A & B 的badge
A = a1 + f1???
B = b1 + f1???
f1到底如何计算???

初始化默认有小红点吗?

info= {
    RJBadgeCountKey = 0;
    RJBadgePathKey = "root.miniLV.page";
    RJBadgeShowKey = 1;
}

子节点的节点上,红点的数量都为0,但是 RJBadgeShowKey = 1导致 根节点上的控件有红点提示.

测试修改

@{RJBadgeNameKey : @"root",
                                                    RJBadgePathKey : @"root",
                                                    RJBadgeCountKey: @(0),
                                                    RJBadgeShowKey : @(NO)};
初始化 - RJBadgeShowKey 设置为NO,最后的info信息里面还是YES,请问是我哪里设置出了问题了吗

controller 的作用探讨

首先感谢作者给出这样一份红点处理系统,真的很好!
但是有一点小疑问:controller 是不是有点多余?

看了一下目录架构,了解到的大致是这样:
• controller 负责外部调用处理协作;
• info 用于携带 block 和 controller 等等需要回调的信息
• model 类负责 tree 的逻辑部分;
• manager 类是负责对接 info (去重)以及递归回调 block;

其实这里面 controller 和 controller 的分类的我认为有点多余,demo 中给出的解释是'为防止循环引用'。但是其实这个 controller 是已经通过 info 携带了。并不需要这层 controller 类。

如果我说的有问题请指教。

父节点消息被清除的回调

你好,如果一个父节点A管理B和C,当B和C都被点击查看了之后,A的红点会被清除,这时候我能监听到A节点被清除吗,badge不是数值模式,我该怎么监听到父节点A红点被清除了呢?

红点显示位置

你好,如果是Masnory布局红点位置会默认显示在左上角,而且当有消息的时候点击push到下一个页面,返回时再请求消息红点显示但是设置的红点偏移量是无效的。

dispatch_queue_async_rjbk went wrong in viewDidLoad

In application: didFinishLaunchingWithOptions:

 UITabBarController *tabVC = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    UITabBarItem *mineItem = tabVC.tabBar.items.lastObject;
    NSString *minePath = @"root.mine";
    
    mineItem.badgeOffset = CGPointMake(5, 5);
    
    [self.badgeController observePath:minePath badgeView:mineItem block:^(id _Nullable observer, NSDictionary<NSString *,id> * _Nonnull info) {
        NSLog(@"%@",info);
    }];
    
    NSString *mineMessagePath = @"root.mine.message";
    
    [RJBadgeController setBadgeForKeyPath:mineMessagePath count:9];

In MineViewController viewDidLoad

    NSString *mineMessagePath = @"root.mine.message";
    [self.badgeController observePath:mineMessagePath badgeView:self.navigationItem.leftBarButtonItem block:^(id _Nullable observer, NSDictionary<NSString *,id> * _Nonnull info) {
        NSLog(@"%@",info);
    }];

leftBarButtonItem in MineViewController did not show the badge, caused by dispatch_queue_async_rjbk did not execute the code!

Use

dispatch_async(dispatch_get_main_queue(), ^{
});

instead.

Need update frame for cutomview in showBadge

refreshBadgeView works well for autolayout with default badge, however, not working for customview.
Should also update self.customView.center inside showBadge just like self.badge.

- (void)showBadge
{
    if (self.customView) {
        self.customView.hidden = NO;
        self.badge.hidden      = YES;
        CGFloat offsetX   = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
        self.customView.center = CGPointMake(offsetX, self.badgeOffset.y);
    } else {        
        CGFloat width = (self.badgeRadius ?: kRJBadgeDefaultRadius) * 2;
        CGRect rect   = CGRectMake(CGRectGetWidth(self.frame), -width, width, width);
        
        self.badge.frame              = rect;
        self.badge.text               = @"";
        self.badge.hidden             = NO;
        self.badge.layer.cornerRadius = width / 2;

        CGFloat offsetX   = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
        self.badge.center = CGPointMake(offsetX, self.badgeOffset.y);
    }
}

没有适配iOS13 小红点位置不对

在iOS13上会发现显示位置都在最左边去了。
遍历UITabBarButton的subViews发现只有在TabBar选中状态下才能取到UITabBarSwappableImageView。

有个小问题,如果在某些场景,希望修改小红点的颜色或者数字色,应该怎么修改?

RJBadgeKit是一个不错的解决方案,但还是有个小问题,需要请教一下
想问一下,如果在某些场景,希望修改小红点的颜色或者数字颜色,应该怎么修改?

比如:有一个场景,导航栏颜色为红色,导航栏item的badge显示数字。
此时,如果badge的背景色显示为红色,总感觉不是很好看,有点看不清。

希望修改bandge的背景色为白色或者其他颜色(非红色就行),文字色改成白色。

我试过,设置customView,貌似没有啥效果。。。。

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.