Skip to content

Commit

Permalink
[BottomNavigation] Add support for custom badge and text colors. (#8518)
Browse files Browse the repository at this point in the history
Allows clients to set a custom badge background and text colors for all
badges. On iOS 10+, the `UITabBarItem badgeColor` API allows customizing
individual items' badge background colors as well. Setting the badge
background and text color will allow clients using badges on Bottom Navigation
to better-support Dark Mode.

Closes #2833
  • Loading branch information
Robert Moore committed Sep 28, 2019
1 parent 86b5971 commit d19d388
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 0 deletions.
11 changes: 11 additions & 0 deletions components/BottomNavigation/src/MDCBottomNavigationBar.h
Expand Up @@ -95,6 +95,17 @@ typedef NS_ENUM(NSInteger, MDCBottomNavigationBarAlignment) {
*/
@property(nonatomic, strong, nonnull) UIFont *itemTitleFont UI_APPEARANCE_SELECTOR;

/**
Background color for badges. Default is a red color. Only applies if the @c UITabBarItem
@c badgeColor is `nil`.
*/
@property(nonatomic, copy, nullable) UIColor *itemBadgeBackgroundColor;

/**
Text color for badges. Default is white.
*/
@property(nonatomic, copy, nullable) UIColor *itemBadgeTextColor;

/**
Color of selected item. Applies color to items' icons and text. If set also sets
selectedItemTitleColor. Default color is black.
Expand Down
28 changes: 28 additions & 0 deletions components/BottomNavigation/src/MDCBottomNavigationBar.m
Expand Up @@ -19,6 +19,7 @@
#import <MDFInternationalization/MDFInternationalization.h>

#import "MaterialMath.h"
#import "MaterialPalettes.h"
#import "MaterialShadowElevations.h"
#import "MaterialShadowLayer.h"
#import "MaterialTypography.h"
Expand Down Expand Up @@ -100,6 +101,9 @@ - (void)commonMDCBottomNavigationBarInit {
_sizeThatFitsIncludesSafeArea = NO;
_titlesNumberOfLines = 1;
_mdc_overrideBaseElevation = -1;
_itemBadgeTextColor = UIColor.whiteColor;
_itemBadgeBackgroundColor = MDCPalette.redPalette.tint700;
;

// Remove any unarchived subviews and reconfigure the view hierarchy
if (self.subviews.count) {
Expand Down Expand Up @@ -535,6 +539,8 @@ - (void)setItems:(NSArray<UITabBarItem *> *)items {
itemView.contentHorizontalMargin = self.itemsContentHorizontalMargin;
itemView.truncatesTitle = self.truncatesLongTitles;
itemView.titlePositionAdjustment = item.titlePositionAdjustment;
itemView.badgeColor = self.itemBadgeBackgroundColor;
itemView.badgeTextColor = self.itemBadgeTextColor;
MDCInkTouchController *controller = [[MDCInkTouchController alloc] initWithView:itemView];
controller.delegate = self;
[self.inkControllers addObject:controller];
Expand Down Expand Up @@ -703,6 +709,28 @@ - (UIColor *)backgroundColor {
return self.barView.backgroundColor;
}

- (void)setItemBadgeTextColor:(UIColor *)itemBadgeTextColor {
_itemBadgeTextColor = itemBadgeTextColor;
for (MDCBottomNavigationItemView *itemView in self.itemViews) {
itemView.badgeTextColor = itemBadgeTextColor;
}
}

- (void)setItemBadgeBackgroundColor:(UIColor *)itemBadgeBackgroundColor {
_itemBadgeBackgroundColor = itemBadgeBackgroundColor;
for (NSUInteger i = 0; i < self.items.count; ++i) {
UITabBarItem *item = self.items[i];
if (@available(iOS 10.0, *)) {
// Skip items with a custom color
if (item.badgeColor) {
continue;
}
}
MDCBottomNavigationItemView *itemView = self.itemViews[i];
itemView.badgeColor = itemBadgeBackgroundColor;
}
}

- (void)setBackgroundBlurEffectStyle:(UIBlurEffectStyle)backgroundBlurEffectStyle {
if (_backgroundBlurEffectStyle == backgroundBlurEffectStyle) {
return;
Expand Down
Expand Up @@ -45,6 +45,7 @@
@property(nonatomic, strong, nullable) UIImage *selectedImage;

@property(nonatomic, strong, nullable) UIColor *badgeColor UI_APPEARANCE_SELECTOR;
@property(nonatomic, copy, nullable) UIColor *badgeTextColor;
@property(nonatomic, strong, nullable) UIColor *selectedItemTintColor UI_APPEARANCE_SELECTOR;
@property(nonatomic, strong, nullable) UIColor *unselectedItemTintColor UI_APPEARANCE_SELECTOR;
@property(nonatomic, strong, nullable) UIColor *selectedItemTitleColor;
Expand Down
Expand Up @@ -511,6 +511,11 @@ - (void)setBadgeColor:(UIColor *)badgeColor {
self.badge.badgeColor = badgeColor;
}

- (void)setBadgeTextColor:(UIColor *)badgeTextColor {
_badgeTextColor = badgeTextColor;
self.badge.badgeValueLabel.textColor = badgeTextColor;
}

- (void)setBadgeValue:(NSString *)badgeValue {
// Due to KVO, badgeValue may be of type NSNull.
if ([badgeValue isKindOfClass:[NSNull class]]) {
Expand Down
Expand Up @@ -445,4 +445,65 @@ - (void)testShadowColorRespondsToDynamicColor {
#endif
}

#pragma mark - Badging

- (void)testCustomBadgeColorsSetAfterItems {
// Given
self.tabItem1.badgeValue = @"";
self.tabItem2.badgeValue = @"Gray on Yellow";
self.tabItem3.badgeValue = @"Gray on Green";
self.navigationBar.frame = CGRectMake(0, 0, MDCBottomNavigationBarTestWidthiPad,
MDCBottomNavigationBarTestHeightTypical);

// When
if (@available(iOS 10.0, *)) {
self.tabItem3.badgeColor = UIColor.greenColor;
}
self.navigationBar.itemBadgeBackgroundColor = UIColor.yellowColor;
self.navigationBar.itemBadgeTextColor = UIColor.darkGrayColor;

// Then
[self generateAndVerifySnapshot];
}

- (void)testCustomBadgeColorsSetBeforeItems {
// Given
self.tabItem1.badgeValue = @"";
self.tabItem2.badgeValue = @"Gray on Yellow";
self.tabItem3.badgeValue = @"Gray on Green";
self.navigationBar.frame = CGRectMake(0, 0, MDCBottomNavigationBarTestWidthiPad,
MDCBottomNavigationBarTestHeightTypical);

// When
if (@available(iOS 10.0, *)) {
self.tabItem3.badgeColor = UIColor.greenColor;
}
self.navigationBar.itemBadgeBackgroundColor = UIColor.yellowColor;
self.navigationBar.itemBadgeTextColor = UIColor.darkGrayColor;
self.navigationBar.items =
@[ self.tabItem1, self.tabItem2, self.tabItem3, self.tabItem4, self.tabItem5 ];

// Then
[self generateAndVerifySnapshot];
}

- (void)testNilBadgeColorsRendersClearBackgroundAndUILabelDefaultTextColor {
// Given
self.tabItem1.badgeValue = @"";
self.tabItem2.badgeValue = @"Black on Clear";
self.tabItem3.badgeValue = @"Black on Green";
self.navigationBar.frame = CGRectMake(0, 0, MDCBottomNavigationBarTestWidthiPad,
MDCBottomNavigationBarTestHeightTypical);

// When
if (@available(iOS 10.0, *)) {
self.tabItem3.badgeColor = UIColor.greenColor;
}
self.navigationBar.itemBadgeBackgroundColor = nil;
self.navigationBar.itemBadgeTextColor = nil;

// Then
[self generateAndVerifySnapshot];
}

@end
Expand Up @@ -104,6 +104,18 @@ - (void)testSetSelectedItemTintColorUpdatesInkColor {
XCTAssertEqualObjects(item1.inkView.inkColor, item2.inkView.inkColor);
}

- (void)testBadgeTextColorSetsBadgeLabelTextColor {
// Given
MDCBottomNavigationItemView *itemView = [[MDCBottomNavigationItemView alloc] init];
itemView.badgeValue = @"123";

// When
itemView.badgeTextColor = UIColor.purpleColor;

// Then
XCTAssertEqualObjects(itemView.badge.badgeValueLabel.textColor, UIColor.purpleColor);
}

- (void)testSetTitleVisibilityUpdatesLayout {
// Given
MDCBottomNavigationItemView *view = [[MDCBottomNavigationItemView alloc] init];
Expand Down
Expand Up @@ -17,6 +17,7 @@
#import "../../src/private/MDCBottomNavigationBar+Private.h"
#import "../../src/private/MDCBottomNavigationItemView.h"
#import "MaterialBottomNavigation.h"
#import "MaterialPalettes.h"
#import "MaterialShadowElevations.h"

/**
Expand Down Expand Up @@ -71,6 +72,8 @@ - (void)testDefaultValues {
0.001);
XCTAssertLessThan(self.bottomNavBar.mdc_overrideBaseElevation, 0);
XCTAssertNil(self.bottomNavBar.mdc_elevationDidChangeBlock);
XCTAssertEqualObjects(self.bottomNavBar.itemBadgeTextColor, UIColor.whiteColor);
XCTAssertEqualObjects(self.bottomNavBar.itemBadgeBackgroundColor, MDCPalette.redPalette.tint700);
}

#pragma mark - Fonts
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d19d388

Please sign in to comment.