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 badge label for buttons #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 6 additions & 0 deletions Example/Controllers/ViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ - (void)viewDidLoad {
[weakSelf showAlertViewWithTitle:@"Globe"
message:@"You have chosen the globe view controller."];
} atIndex:4];

// tabBarController.badgeFont = [UIFont systemFontOfSize:10 weight:2];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's don't leave commented lines of code here :)

We could instead leave a comment that says:

// For more customisation of badge labels, see properties in ESTabBarController.h.

// tabBarController.badgeOffset = 10;
// tabBarController.badgeSize = 20;
// tabBarController.badgeTextColor = [UIColor colorWithHexString:@"#F6EBE0"];
[tabBarController setBadgeValue:@"99" atIndex:0];
}


Expand Down
59 changes: 58 additions & 1 deletion Source/Categories/ESTabBarController+Autolayout.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ @interface ESTabBarController ()
@property (nonatomic, weak) UIView *controllersContainer;
@property (nonatomic, weak) UIView *buttonsContainer;
@property (nonatomic, strong) NSMutableArray *buttons;
@property (nonatomic, strong) NSMutableArray *badgeLabels;
@property (nonatomic, assign) NSArray *tabIcons;
@property (nonatomic, strong) UIView *selectionIndicator;
@property (nonatomic, strong) NSLayoutConstraint *selectionIndicatorLeadingConstraint;
Expand All @@ -36,10 +37,16 @@ - (void)setupButtonsConstraints {
[self.view addConstraints:[self verticalLayoutConstraintsForButtonAtIndex:i]];
[self.view addConstraint:[self widthLayoutConstraintForButtonAtIndex:i]];
[self.view addConstraint:[self heightLayoutConstraintForButtonAtIndex:i]];

[self.badgeLabels[i] setTranslatesAutoresizingMaskIntoConstraints:NO];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method, setupButtonsConstraints, is intended to only setup constraints for buttons. Would you rather add a method like - (void)setupBadgeLabelsConstraints?

I think it's going to look neater.


[self.view addConstraint:[self horizontalLayoutConstraintsForBadgeLabelAtIndex:i]];
[self.view addConstraint:[self verticalLayoutConstraintsForBadgeLabelAtIndex:i]];
[self.view addConstraint:[self widthLayoutConstraintForBadgeLabelAtIndex:i]];
[self.view addConstraint:[self heightLayoutConstraintForBadgeLabelAtIndex:i]];
}
}


- (void)setupSelectionIndicatorConstraints {
self.selectionIndicatorLeadingConstraint = [self leadingLayoutConstraintForIndicator];

Expand Down Expand Up @@ -168,5 +175,55 @@ - (NSArray *)bottomLayoutConstraintsForIndicator {
views:@{@"selectionIndicator": self.selectionIndicator}];
}

- (NSLayoutConstraint *)widthLayoutConstraintForBadgeLabelAtIndex:(NSInteger)index {
UILabel *label = self.badgeLabels[index];

return [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeWidth
multiplier:1.0f
constant:self.badgeSize];
}


- (NSLayoutConstraint *)heightLayoutConstraintForBadgeLabelAtIndex:(NSInteger)index {
UILabel *label = self.badgeLabels[index];

return [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeHeight
multiplier:1.0f
constant:self.badgeSize];
}

- (NSLayoutConstraint *)verticalLayoutConstraintsForBadgeLabelAtIndex:(NSInteger)index {
UILabel *label = self.badgeLabels[index];
UIButton *button = self.buttons[index];

return [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:button
attribute:NSLayoutAttributeCenterY
multiplier:1.0
constant:-self.badgeOffset];
}

- (NSLayoutConstraint *)horizontalLayoutConstraintsForBadgeLabelAtIndex:(NSInteger)index {
UILabel *label = self.badgeLabels[index];
UIButton *button = self.buttons[index];

return [NSLayoutConstraint constraintWithItem:label
attribute:NSLayoutAttributeCenterX
relatedBy:NSLayoutRelationEqual
toItem:button
attribute:NSLayoutAttributeCenterX
multiplier:1.0
constant:self.badgeOffset];
}

@end
21 changes: 21 additions & 0 deletions Source/Controllers/ESTabBarController.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,22 @@ typedef void (^ESTabBarAction)(void);
// ones a bit transparent.
@property (nonatomic, assign) BOOL highlightsSelectedButton;

// Color to use for badge text
// Defaults to [UIColor whiteColor]
@property (nonatomic, strong) UIColor *badgeTextColor;

// Font for badge text
// Defaults to [UIFont systemFontOfSize:8]
@property (nonatomic, strong) UIFont *badgeFont;

// Badge width and height in pt
// Defaults to 16
@property (nonatomic, assign) NSInteger badgeSize;

// Badge offset from button's center (up and right)
// Defaults to 12
@property (nonatomic, assign) NSInteger badgeOffset;


/**
Initializes the tab bar with an array of UIImage that will be the icons
Expand Down Expand Up @@ -88,5 +104,10 @@ typedef void (^ESTabBarAction)(void);
*/
- (void)setSelectedIndex:(NSInteger)selectedIndex animated:(BOOL)animated;

/**
Sets the badge text value.
Set nil to remove badge.
*/
- (void)setBadgeValue:(NSString*)value atIndex:(NSInteger)index;

@end
50 changes: 49 additions & 1 deletion Source/Controllers/ESTabBarController.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ @interface ESTabBarController ()
@property (nonatomic, assign) BOOL didSetupInterface;
@property (nonatomic, strong) NSMutableArray *buttons;
@property (nonatomic, strong) NSMutableSet *highlightedButtonIndexes;
@property (nonatomic, strong) NSMutableDictionary *badgeValues;
@property (nonatomic, strong) NSMutableArray *badgeLabels;
@property (nonatomic, strong) NSArray *tabIcons;
@property (nonatomic, strong) UIView *selectionIndicator;
@property (nonatomic, strong) NSLayoutConstraint *selectionIndicatorLeadingConstraint;
Expand Down Expand Up @@ -180,6 +182,17 @@ - (void)setSelectedIndex:(NSInteger)selectedIndex animated:(BOOL)animated {
}
}

- (void)setBadgeValue:(NSString*)value atIndex:(NSInteger)index
{
NSString* key = [NSString stringWithFormat:@"%ld", (long)index];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For controllers and actions, I'm using NSNumbers as keys, instead of strings. Would be nice if we can keep that to preserve the consistency. If then, this method would look like:

- (void)setBadgeValue:(NSString *)value atIndex:(NSInteger)index {
    if (value) {
        self.badgeValues[@(index)] = value;
    } else {
        [self.badgeValues removeObjectForKey:@(index)];
    }

    [self updateInterfaceIfNeeded];
}

if (value) {
[self.badgeValues setValue:value forKey:key];
}
else {
[self.badgeValues removeObjectForKey:key];
}
[self updateInterfaceIfNeeded];
}

#pragma mark - Actions

Expand All @@ -206,11 +219,18 @@ - (void)initializeWithTabIcons:(NSArray *)tabIcons {
self.actions = [NSMutableDictionary dictionaryWithCapacity:tabIcons.count];

self.highlightedButtonIndexes = [NSMutableSet set];
self.badgeValues = [NSMutableDictionary dictionaryWithCapacity:tabIcons.count];

// No selected index at first.
_selectedIndex = -1;

self.separatorLineColor = [UIColor lightGrayColor];

self.badgeTextColor = [UIColor whiteColor];
self.badgeFont = [UIFont systemFontOfSize:8];
self.badgeSize = 16;
self.badgeOffset = 12;

}


Expand All @@ -233,12 +253,17 @@ - (void)setupInterface {
- (void)setupButtons {
if (self.buttons == nil) {
self.buttons = [NSMutableArray arrayWithCapacity:self.tabIcons.count];
self.badgeLabels = [NSMutableArray arrayWithCapacity:self.tabIcons.count];

for (NSInteger i = 0; i < self.tabIcons.count; i++) {
UIButton *button = [self createButtonForIndex:i];

[self.buttonsContainer addSubview:button];
self.buttons[i] = button;

UILabel *badgeLabel = [self createBadgeLabel];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if we can take the badges setup to another method, say - (void)setupBadeLabels.

[self.buttonsContainer addSubview:badgeLabel];
self.badgeLabels[i] = badgeLabel;
}

[self setupButtonsConstraints];
Expand All @@ -259,6 +284,20 @@ - (UIButton *)createButtonForIndex:(NSInteger)index {
return button;
}

- (UILabel*)createBadgeLabel
{
UILabel *label = [UILabel new];

label.font = self.badgeFont;
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = self.selectedColor;
label.textColor = self.badgeTextColor ?: [UIColor whiteColor];
label.layer.cornerRadius = self.badgeSize / 2;
label.layer.masksToBounds = YES;

return label;
}


- (void)customizeButtons {
for (NSInteger i = 0; i < self.tabIcons.count; i++) {
Expand All @@ -268,7 +307,16 @@ - (void)customizeButtons {
[button customizeForTabBarWithImage:self.tabIcons[i]
selectedColor:self.selectedColor ?: [UIColor blackColor]
highlighted:isHighlighted];


UILabel *badgeLabel = self.badgeLabels[i];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment for this, would be nice if we can take this logic to a - (void)customizeLabel method.

NSString* badgeValue = [self.badgeValues valueForKey:[NSString stringWithFormat:@"%ld", (long)i]];
if (badgeValue) {
badgeLabel.text = badgeValue;
badgeLabel.hidden = NO;
}
else {
badgeLabel.hidden = YES;
}
}
}

Expand Down