Robert Moore b1e9182aaf
[BottomNavigation] Simplify and improve badge view. (#6544)
## Visual Improvements
Improves the badge view to better match the [Material.io guidelines article for Bottom Navigation](https://material.io/design/components/bottom-navigation.html#behavior).  It decreases the horizontal margins on either side of the text to provide a more circular shape when few numerals are present. It also adds support for a dedicated empty badge where no text is provided instead of relying on a string of spaces. 

<img width="728" alt="material-bottomnav-badge-example" src="https://user-images.githubusercontent.com/1753199/52158868-bc5b4e00-266a-11e9-8bad-a5d7bc7567d4.png">

Here is the typical use example bar in the Dragons catalog as it appears after this change:

|State|Image|
|---|---|
|Before|![badge-layout-develop](https://user-images.githubusercontent.com/1753199/52159942-6b068b00-2679-11e9-974a-e813aa211d09.png)|
|After|![badge-layout-trig](https://user-images.githubusercontent.com/1753199/52160891-41565f80-268b-11e9-9d4d-94cad201cb4a.png)|

And an overlay of the Material guidelines version and this PR for an empty badge:
<img width="530" alt="material-mdcios-comparison" src="https://user-images.githubusercontent.com/1753199/52159041-0fce9b80-266d-11e9-8458-80487a90672c.png">

Test rendering using Japanese kanji indicates that the new margin values are sufficient for characters extending to the corners of the label. (The text was chosen because the characters use much of the glyph space.)

|Before|After|
|---|---|
|![badge-layout-japanese-double-develop](https://user-images.githubusercontent.com/1753199/52160215-2ed62900-267f-11e9-80f9-4ec014c663b8.png)|![badge-layout-trig-japanese-double](https://user-images.githubusercontent.com/1753199/52160890-38fe2480-268b-11e9-862b-27d17bb688f8.png)|

Calculating the horizontal padding needs careful consideration because some scripts can place glyphs right at the edge of the UILabel's bounds. For example, the RTL/Arabic tests in #6543 use a *lorem ipsum* in Arabic script that includes glyphs bumping right up against the edge of the badge.
<img width="60" alt="badge-layout-arabic-script" src="https://user-images.githubusercontent.com/1753199/52160919-af9b2200-268b-11e9-9d99-0ee7df2de054.png">


A follow-up PR for MDCBottomNavigationItemView will improve the positioning of the badge.

## Technical refactoring and simplification
As part of the visual improvement the badge will respect its bounds during layout and no longer changes its own frame. The addition of `sizeToFit` and `sizeThatFits:` makes layout in the Bottom Navigation bar simpler. The badge no longer requires a layout pass to determine its size.  Several superfluous properties were removed and internal constants were adjusted to improve the design.

Part of #6520 

Internal tests performed in cl/232081379
2019-02-04 09:18:14 -05:00

143 lines
5.7 KiB
Objective-C

// Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#import <UIKit/UIKit.h>
#import "BottomNavigationTypicalUseSupplemental.h"
#import "MaterialBottomNavigation+ColorThemer.h"
#import "MaterialBottomNavigation+TypographyThemer.h"
#import "MaterialBottomNavigation.h"
#import "MaterialPalettes.h"
@interface BottomNavigationTypicalUseExample () <MDCBottomNavigationBarDelegate>
@property(nonatomic, assign) int badgeCount;
@property(nonatomic, strong) MDCBottomNavigationBar *bottomNavBar;
@end
@implementation BottomNavigationTypicalUseExample
- (id)init {
self = [super init];
if (self) {
self.title = @"Bottom Navigation";
_colorScheme =
[[MDCSemanticColorScheme alloc] initWithDefaults:MDCColorSchemeDefaultsMaterial201804];
_typographyScheme = [[MDCTypographyScheme alloc] init];
}
return self;
}
- (void)commonBottomNavigationTypicalUseExampleViewDidLoad {
_bottomNavBar = [[MDCBottomNavigationBar alloc] initWithFrame:CGRectZero];
_bottomNavBar.titleVisibility = MDCBottomNavigationBarTitleVisibilitySelected;
_bottomNavBar.alignment = MDCBottomNavigationBarAlignmentJustifiedAdjacentTitles;
_bottomNavBar.delegate = self;
[self.view addSubview:_bottomNavBar];
UITabBarItem *tabBarItem1 = [[UITabBarItem alloc] initWithTitle:@"Home"
image:[UIImage imageNamed:@"Home"]
tag:0];
UITabBarItem *tabBarItem2 = [[UITabBarItem alloc] initWithTitle:@"Messages"
image:[UIImage imageNamed:@"Email"]
tag:0];
tabBarItem2.badgeValue = @"";
UITabBarItem *tabBarItem3 = [[UITabBarItem alloc] initWithTitle:@"Favorites"
image:[UIImage imageNamed:@"Favorite"]
tag:0];
tabBarItem3.badgeValue = @"8";
UITabBarItem *tabBarItem4 = [[UITabBarItem alloc] initWithTitle:@"Search"
image:[UIImage imageNamed:@"Search"]
tag:0];
tabBarItem4.badgeValue = @"88";
UITabBarItem *tabBarItem5 = [[UITabBarItem alloc] initWithTitle:@"Birthday"
image:[UIImage imageNamed:@"Cake"]
tag:0];
tabBarItem5.badgeValue = @"888+";
#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
if ([tabBarItem5 respondsToSelector:@selector(badgeColor)]) {
tabBarItem5.badgeColor = [MDCPalette cyanPalette].accent700;
}
#pragma clang diagnostic pop
#endif
_bottomNavBar.items = @[ tabBarItem1, tabBarItem2, tabBarItem3, tabBarItem4, tabBarItem5 ];
_bottomNavBar.selectedItem = tabBarItem2;
self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:@"+Message"
style:UIBarButtonItemStylePlain
target:self
action:@selector(updateBadgeItemCount)];
self.navigationItem.rightBarButtonItem.accessibilityLabel = @"Add a message";
self.navigationItem.rightBarButtonItem.accessibilityHint =
@"Increases the badge on the \"Messages\" tab.";
self.navigationItem.rightBarButtonItem.accessibilityIdentifier = @"messages-increment-badge";
}
- (void)layoutBottomNavBar {
CGSize size = [_bottomNavBar sizeThatFits:self.view.bounds.size];
CGRect bottomNavBarFrame =
CGRectMake(0, CGRectGetHeight(self.view.bounds) - size.height, size.width, size.height);
_bottomNavBar.frame = bottomNavBarFrame;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self commonBottomNavigationTypicalUseExampleViewDidLoad];
[MDCBottomNavigationBarTypographyThemer applyTypographyScheme:self.typographyScheme
toBottomNavigationBar:_bottomNavBar];
[MDCBottomNavigationBarColorThemer applySemanticColorScheme:self.colorScheme
toBottomNavigation:_bottomNavBar];
self.view.backgroundColor = self.colorScheme.backgroundColor;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self layoutBottomNavBar];
}
- (void)viewSafeAreaInsetsDidChange {
if (@available(iOS 11.0, *)) {
[super viewSafeAreaInsetsDidChange];
}
[self layoutBottomNavBar];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)updateBadgeItemCount {
// Example of badge with increasing count.
if (!self.badgeCount) {
self.badgeCount = 0;
}
self.badgeCount++;
self.bottomNavBar.items[1].badgeValue = [NSNumber numberWithInt:self.badgeCount].stringValue;
}
#pragma mark - MDCBottomNavigationBarDelegate
- (void)bottomNavigationBar:(nonnull MDCBottomNavigationBar *)bottomNavigationBar
didSelectItem:(nonnull UITabBarItem *)item {
NSLog(@"Selected Item: %@", item.title);
}
@end