Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add UIBarButtonItem Support #15

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions Example/RJBadgeKit/RJDemoViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,28 @@ - (void)viewDidLoad

[self.badgeController observePath:demoPath badgeView:self.pageButton block:nil];

UIButton *mark = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 12.0f, 25, 25.f)];
mark.badgeOffset = CGPointMake(-2, 6);

UIBarButtonItem *mark = [[UIBarButtonItem alloc] initWithTitle:@"mark" style:UIBarButtonItemStylePlain target:self action:@selector(markAction:)];
self.navigationItem.rightBarButtonItem = mark;

[RJBadgeController setBadgeForKeyPath:RJMarkPath];
// // mark.badgeOffset = CGPointMake(0, 0); //It do not work, use:
// self.navigationItem.rightBarButtonItem.badgeOffset = CGPointMake(0, 0);

[self.badgeController observePath:RJMarkPath badgeView:mark block:nil];
[RJBadgeController setBadgeForKeyPath:RJMarkPath];

[mark setTitle:@"Mark" forState:UIControlStateNormal];
[mark setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[mark addTarget:self action:@selector(markAction:) forControlEvents:(UIControlEventTouchUpInside)];
// [self.badgeController observePath:RJMarkPath badgeView:mark block:nil];//It do not work, use:
[self.badgeController observePath:RJMarkPath badgeView:self.navigationItem.rightBarButtonItem block:nil];


UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:mark];
self.navigationItem.rightBarButtonItem = barItem;
}

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

// After the navigationBar initialization is completed
self.navigationItem.rightBarButtonItem.badgeOffset = CGPointMake(0, 0);

/**
@note Example for refresh badge display of -'mark' button on navigation bar,
which may not appear at first due to autolayout procedure of navigation items.
Expand Down
Empty file modified RJBadgeKit/Classes/BadgeController/NSObject+RJBadgeController.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeController/NSObject+RJBadgeController.m
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeController/RJBadgeController.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeController/RJBadgeController.m
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeController/RJBadgeManager.h
100644 → 100755
Empty file.
21 changes: 6 additions & 15 deletions RJBadgeKit/Classes/BadgeController/RJBadgeManager.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,6 @@
#import "UIView+RJBadge.h"
#import "RJBadgeController.h"

#ifndef dispatch_queue_async_rjbk
#define dispatch_queue_async_rjbk(queue, block)\
if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) { \
block(); \
} else { \
dispatch_async(queue, block); \
}
#endif

#ifndef dispatch_main_async_rjbk
#define dispatch_main_async_rjbk(block) dispatch_queue_async_rjbk(dispatch_get_main_queue(), block)
#endif

NS_ASSUME_NONNULL_BEGIN

Expand Down Expand Up @@ -133,7 +121,9 @@ - (void)unobserveWithInfo:(nullable RJBadgeInfo *)info
pthread_mutex_unlock(&_mutex);

if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
dispatch_main_async_rjbk(^{ [badgeView hideBadge]; });
dispatch_async(dispatch_get_main_queue(), ^{
[badgeView hideBadge];
});
}
}

Expand Down Expand Up @@ -283,7 +273,8 @@ - (void)statusChangeForBadges:(NSArray<id<RJBadge>> *)badges
id<RJBadgeView> badgeView = bInfo.badgeView;
if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
NSUInteger c = badge.count;
dispatch_main_async_rjbk(^{

dispatch_async(dispatch_get_main_queue(), ^{
if (c > 0) {
[badgeView showBadgeWithValue:c];
} else if (badge.needShow) {
Expand Down Expand Up @@ -313,7 +304,7 @@ - (void)refreshBadgeWithInfos:(NSHashTable<RJBadgeInfo *> *)infos
id<RJBadgeView> badgeView = bInfo.badgeView;
if (badgeView && [badgeView conformsToProtocol:@protocol(RJBadgeView)]) {
NSUInteger c = badge.count;
dispatch_main_async_rjbk(^{
dispatch_async(dispatch_get_main_queue(), ^{
if (c > 0) {
[badgeView showBadgeWithValue:c];
} else if (badge.needShow) {
Expand Down
Empty file modified RJBadgeKit/Classes/BadgeModel/RJBadge.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeModel/RJBadgeInfo.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeModel/RJBadgeInfo.m
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeModel/RJBadgeModel.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeModel/RJBadgeModel.m
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeView/RJBadgeView.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/BadgeView/UIBarButtonItem+RJBadge.h
100644 → 100755
Empty file.
74 changes: 72 additions & 2 deletions RJBadgeKit/Classes/BadgeView/UIBarButtonItem+RJBadge.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,80 @@ - (void)showBadgeWithValue:(NSUInteger)value {
}

#pragma mark - private method
- (UIView *)badgeView {
return [self valueForKeyPath:@"_view"];

// po [[self valueForKeyPath:@"_view"] performSelector:@selector(class)]
// po [[self valueForKeyPath:@"_view"] performSelector:@selector(subviews)]

- (UIView *)badgeView
{
UIView *bottomView = [self valueForKeyPath:@"_view"];
UIView *targetView = nil;
if (bottomView) {
targetView = [self findTargetViewInView:bottomView];
targetView.clipsToBounds = NO;
}
return targetView;
}


// iOS10 iOS9 iOS8 (UINavigationBar →)

// UINavigationButton → UIImageView //initWithImage,initWithBarButtonSystemItem
// UINavigationButton → UIButtonLabel(UILable) //initWithBarButtonSystemItem,initWithTitle
// CustomView //initWithCustomView


// iOS11 (UINavigationBar → _UINavigationBarContentView → _UIButtonBarStackView →)

// _UIButtonBarButton → _UIModernBarButton → UIImageView //initWithImage,initWithBarButtonSystemItem
// _UIButtonBarButton → _UIModernBarButton → UIButtonLabel(UILable) //initWithBarButtonSystemItem,initWithTitle
// (_UIButtonBarButton → _UITAMICAdaptorView →) CustomView //initWithCustomView


- (UIView *)findTargetViewInView:(UIView *)view
{
__block UIView *targetView = nil;

if ([[UIDevice currentDevice].systemVersion doubleValue] < 10.9) {
if ([view isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
[view.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
if ([subview isKindOfClass:UIImageView.class] ||
[subview isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
targetView = subview;
}
if (targetView) {
*stop = YES;
}
}];
}else{
targetView = view;
}
}else{
if ([view isKindOfClass:NSClassFromString(@"_UIButtonBarButton")]) {

[view.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
if ([subview isKindOfClass:NSClassFromString(@"_UIModernBarButton")]) {
if ([subview.subviews.firstObject isKindOfClass:UIImageView.class] ||
[subview.subviews.firstObject isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
targetView = subview.subviews.firstObject;
}
}
if (targetView) {
*stop = YES;
}
}];
}else{
targetView = view;
}
}

if (targetView == nil) {
NSLog(@"TargetView of UIBarButtonItem Not Found!");
}
return targetView;
}


#pragma mark - setter/getter
- (UILabel *)badge {
return [self badgeView].badge;
Expand Down
Empty file modified RJBadgeKit/Classes/BadgeView/UITabBarItem+RJBadge.h
100644 → 100755
Empty file.
6 changes: 3 additions & 3 deletions RJBadgeKit/Classes/BadgeView/UITabBarItem+RJBadge.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ - (void)showBadgeWithValue:(NSUInteger)value {
- (UIView *)badgeView
{
UIView *bottomView = [self valueForKeyPath:@"_view"]; // UITabbarButtion
UIView *parentView = nil; // UIImageView
UIView *targetView = nil; // UIImageView
if (bottomView) {
parentView = [self find:bottomView
targetView = [self find:bottomView
firstSubviewWithClass:NSClassFromString(@"UITabBarSwappableImageView")];
}
return parentView;
return targetView;
}

- (UIView *)find:(UIView *)view firstSubviewWithClass:(Class)cls
Expand Down
Empty file modified RJBadgeKit/Classes/BadgeView/UIView+RJBadge.h
100644 → 100755
Empty file.
113 changes: 44 additions & 69 deletions RJBadgeKit/Classes/BadgeView/UIView+RJBadge.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,24 @@
#import "UIView+RJBadge.h"
#import <objc/runtime.h>

#define kRJBadgeDefaultFont ([UIFont boldSystemFontOfSize:9])
#define kRJBadgeDefaultFont ([UIFont boldSystemFontOfSize:12])
#define kRJBadgeDefaultMaximumBadgeNumber 99

static const CGFloat kRJBadgeDefaultRadius = 3.f;
static const CGFloat kRJBadgeDefaultRadius = 4.f;

@implementation UIView (RJBadge)

#pragma mark - RJBadgeView
- (void)showBadge
{
CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
CGPoint center = CGPointMake(offsetX, self.badgeOffset.y);

if (self.badgeCustomView) {
self.badgeCustomView.hidden = NO;
self.badge.hidden = YES;
self.badgeCustomView.center = center;
[self adjustCustomViewFrame:self.badgeCustomView];
} else {
CGFloat w = (self.badgeRadius ? : kRJBadgeDefaultRadius) * 2;
CGRect r = CGRectMake(CGRectGetWidth(self.frame), -w, w, w);

self.badge.frame = r;
self.badge.text = @"";
self.badge.hidden = NO;
self.badge.layer.cornerRadius = w / 2;
self.badge.center = center;
[self adjustDotFrame:self.badge];
}
}

Expand All @@ -47,20 +39,7 @@ - (void)showBadgeWithValue:(NSUInteger)value
self.badge.text = (value > kRJBadgeDefaultMaximumBadgeNumber ?
[NSString stringWithFormat:@"%@+", @(kRJBadgeDefaultMaximumBadgeNumber)] :
[NSString stringWithFormat:@"%@" , @(value)]);
[self adjustLabelWidth:self.badge];

CGRect frame = self.badge.frame;
frame.size.width += 4;
frame.size.height += 4;

if(CGRectGetWidth(frame) < CGRectGetHeight(frame)) {
frame.size.width = CGRectGetHeight(frame);
}
self.badge.frame = frame;
CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
self.badge.center = CGPointMake(offsetX, self.badgeOffset.y);

self.badge.layer.cornerRadius = CGRectGetHeight(self.badge.frame) / 2.f;
[self adjustLabelFrame:self.badge];
}

- (void)hideBadge
Expand All @@ -72,59 +51,61 @@ - (void)hideBadge
}

#pragma mark - private methods
- (void)adjustLabelWidth:(UILabel *)label

- (void)adjustCustomViewFrame:(UIView *)customView{
CGFloat offsetX = CGRectGetWidth(self.bounds) + self.badgeOffset.x;
customView.center = CGPointMake(offsetX, self.badgeOffset.y);
}

- (void)adjustDotFrame:(UILabel *)label
{
[label setNumberOfLines:0];

NSString *s = label.text;
UIFont *font = [label font];
CGSize size = CGSizeMake(320,2000);
CGFloat width = (self.badgeRadius ?: kRJBadgeDefaultRadius) * 2;
label.bounds = CGRectMake(0, 0, width, width);
label.layer.cornerRadius = width / 2;

CGFloat offsetX = CGRectGetWidth(self.bounds) + self.badgeOffset.x;
label.center = CGPointMake(offsetX, self.badgeOffset.y);
}

- (void)adjustLabelFrame:(UILabel *)label
{
CGSize labelsize = CGSizeZero;
labelsize = [label.text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX,CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName: label.font}
context:nil].size;


if (![s respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
labelsize = [s sizeWithFont:font
constrainedToSize:size
lineBreakMode:NSLineBreakByWordWrapping];
#pragma clang diagnostic pop
} else {
NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];

labelsize = [s boundingRectWithSize:size
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:@{NSFontAttributeName: font, NSParagraphStyleAttributeName: style}
context:nil].size;
}
CGRect frame = label.frame;
frame.size = CGSizeMake(ceilf(labelsize.width), ceilf(labelsize.height));
[label setFrame:frame];
label.bounds = CGRectMake(0,
0,
ceilf(MAX(labelsize.width, labelsize.height)) + 2,
ceilf(labelsize.height) + 2);

CGFloat offsetX = CGRectGetWidth(self.bounds) + self.badgeOffset.x;
label.center = CGPointMake(offsetX, self.badgeOffset.y);

label.layer.cornerRadius = CGRectGetHeight(label.bounds) / 2.f;
}

#pragma mark - setter/getter
- (UILabel *)badge
{
UILabel *bLabel = objc_getAssociatedObject(self, _cmd);
if (!bLabel) {
CGFloat width = kRJBadgeDefaultRadius * 2;
CGRect rect = CGRectMake(CGRectGetWidth(self.frame), -width, width, width);
bLabel = [[UILabel alloc] initWithFrame:rect];
bLabel = [[UILabel alloc] initWithFrame:CGRectZero];
bLabel.textAlignment = NSTextAlignmentCenter;
bLabel.backgroundColor = [UIColor colorWithRed: 1.f
green: 93.f/225.f
blue:165.f/255.f
bLabel.backgroundColor = [UIColor colorWithRed:0xFB/225.f
green:0x2E/225.f
blue:0x35/255.f
alpha:1.f];
bLabel.textColor = [UIColor whiteColor];
bLabel.text = @"";
// CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
// bLabel.center = CGPointMake(offsetX, self.badgeOffset.y);

bLabel.layer.cornerRadius = kRJBadgeDefaultRadius;
bLabel.layer.masksToBounds = YES;
bLabel.hidden = YES;

[self adjustDotFrame:bLabel];

objc_setAssociatedObject(self,
_cmd,
bLabel,
Expand Down Expand Up @@ -228,22 +209,16 @@ - (UIView *)badgeCustomView {
- (void)setBadgeCustomView:(UIView *)badgeCustomView
{
if (self.badgeCustomView == badgeCustomView) return;

if (self.badgeCustomView) [self.badgeCustomView removeFromSuperview];
if (badgeCustomView) [self addSubview:badgeCustomView];

objc_setAssociatedObject(self,
@selector(badgeCustomView),
badgeCustomView,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);

if (self.badgeCustomView) {
CGRect bound = badgeCustomView.bounds;
bound.origin.x = CGRectGetWidth(self.frame);
bound.origin.y = -bound.size.height;

self.badgeCustomView.frame = bound;
// CGFloat offsetX = CGRectGetWidth(self.frame) + 2 + self.badgeOffset.x;
// self.badgeCustomView.center = CGPointMake(offsetX, self.badgeOffset.y);
[self addSubview:self.badgeCustomView];
}
[self showBadge]; // refresh - in case of setting custom view after show badge
}
Expand Down
Empty file modified RJBadgeKit/Classes/Helper/NSString+RJBadge.h
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/Helper/NSString+RJBadge.m
100644 → 100755
Empty file.
Empty file modified RJBadgeKit/Classes/RJBadgeKit.h
100644 → 100755
Empty file.