blob: 7a68c13f958921c0d8154642e30e78727adea4b4 [file] [log] [blame] [edit]
// 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 "MDCBottomNavigationItemBadge.h"
#import <CoreGraphics/CoreGraphics.h>
#import "MaterialPalettes.h"
// This is very close to the material.io guidelines article considering the fonts differ.
static const CGFloat kBadgeFontSize = 8;
// These padding values get pretty close to the material.io guidelines article.
static const CGFloat kBadgeYPadding = 2;
// For an empty badge, ensure that the size is close to the guidelines article.
static const CGFloat kMinDiameter = 9;
@implementation MDCBottomNavigationItemBadge
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self commonMDCBottomNavigationItemBadgeInit];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self commonMDCBottomNavigationItemBadgeInit];
}
return self;
}
- (void)commonMDCBottomNavigationItemBadgeInit {
if (!_badgeColor) {
_badgeColor = MDCPalette.redPalette.tint700;
}
self.layer.backgroundColor = _badgeColor.CGColor;
if (self.subviews.count == 0) {
_badgeValueLabel = [[UILabel alloc] initWithFrame:self.bounds];
_badgeValueLabel.textColor = [UIColor whiteColor];
_badgeValueLabel.font = [UIFont systemFontOfSize:kBadgeFontSize];
_badgeValueLabel.textAlignment = NSTextAlignmentCenter;
_badgeValueLabel.isAccessibilityElement = NO;
_badgeValueLabel.text = _badgeValue;
[self addSubview:_badgeValueLabel];
} else {
// Badge label was restored during -initWithCoder:
_badgeValueLabel = self.subviews.firstObject;
}
}
- (CGFloat)badgeXPaddingForRadius:(CGFloat)radius {
CGFloat badgeXPadding = (CGFloat)(sin(M_PI_4) * (radius)); // sin(ΓΈ) = badgeXPadding / radius
badgeXPadding += 1; // Extra point to ensure some background extends beyond the label.
// Align to the nearest pixel
badgeXPadding = round(badgeXPadding * self.contentScaleFactor) / self.contentScaleFactor;
return badgeXPadding;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat badgeRadius = CGRectGetHeight(self.bounds) / 2;
CGRect availableContentRect = CGRectStandardize(
CGRectInset(self.bounds, [self badgeXPaddingForRadius:badgeRadius], kBadgeYPadding));
CGSize labelFitSize = [self.badgeValueLabel sizeThatFits:availableContentRect.size];
self.badgeValueLabel.bounds = CGRectMake(0, 0, labelFitSize.width, labelFitSize.height);
self.badgeValueLabel.center =
CGPointMake(CGRectGetMidX(availableContentRect), CGRectGetMidY(availableContentRect));
self.layer.cornerRadius = badgeRadius;
self.layer.backgroundColor = self.badgeColor.CGColor;
}
- (CGSize)sizeThatFits:(CGSize)size {
if (self.badgeValue == nil) {
return CGSizeZero;
}
// Calculate the badge and label heights
CGSize labelSize = [self.badgeValueLabel sizeThatFits:size];
CGFloat badgeHeight = labelSize.height + kBadgeYPadding;
CGFloat contentXPadding = [self badgeXPaddingForRadius:badgeHeight / 2];
CGFloat badgeWidth = labelSize.width + contentXPadding;
badgeWidth = MAX(kMinDiameter, badgeWidth);
badgeHeight = MAX(kMinDiameter, badgeHeight);
if (badgeWidth < badgeHeight) {
badgeWidth = badgeHeight;
}
return CGSizeMake(badgeWidth, badgeHeight);
}
- (void)setBadgeValue:(NSString *)badgeValue {
_badgeValue = badgeValue;
self.badgeValueLabel.text = badgeValue;
[self setNeedsLayout];
}
- (void)setBadgeColor:(UIColor *)badgeColor {
_badgeColor = badgeColor;
self.layer.backgroundColor = _badgeColor.CGColor;
}
@end