Commit 6cb8ff4e authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

Add number and text badge to the tools menu items

This CL adds two badges, mutually exclusives, to the tools menu items.
Those badge can have text or number.

Bug: 826304
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I497c3332f12be2cd4869ab9857959ac87cfa81e4
Reviewed-on: https://chromium-review.googlesource.com/987894Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#547723}
parent c7555d3a
...@@ -15,8 +15,11 @@ source_set("cells") { ...@@ -15,8 +15,11 @@ source_set("cells") {
] ]
deps = [ deps = [
"//base", "//base",
"//ios/chrome/browser/ui/reading_list:reading_list_ui",
"//ios/chrome/browser/ui/table_view:styler",
"//ios/chrome/browser/ui/table_view/cells", "//ios/chrome/browser/ui/table_view/cells",
"//ios/chrome/browser/ui/util:constraints_ui", "//ios/chrome/browser/ui/util:constraints_ui",
"//ios/chrome/common",
] ]
libs = [ "UIKit.framework" ] libs = [ "UIKit.framework" ]
} }
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
@property(nonatomic, strong) UIImage* image; @property(nonatomic, strong) UIImage* image;
// Whether the cell associated with this item should be enabled. // Whether the cell associated with this item should be enabled.
@property(nonatomic, assign) BOOL enabled; @property(nonatomic, assign) BOOL enabled;
// Number to be displayed in the badge.
@property(nonatomic, assign) NSInteger badgeNumber;
// Text to be displayed in the badge. Set to nil to hide the badge.
@property(nonatomic, copy) NSString* badgeText;
@end @end
...@@ -29,9 +33,10 @@ ...@@ -29,9 +33,10 @@
// Title label for the cell. // Title label for the cell.
@property(nonatomic, strong, readonly) UILabel* titleLabel; @property(nonatomic, strong, readonly) UILabel* titleLabel;
// Returns the size this cell would use to display its content when it has a // Sets the number on the badge number.
// |title| and a maximum |width|. - (void)setBadgeNumber:(NSInteger)badgeNumber;
+ (CGSize)sizeForWidth:(CGFloat)width title:(NSString*)title; // Sets the text of the badge text. Hides the badge text if |badgeText| is nil.
- (void)setBadgeText:(NSString*)badgeText;
@end @end
......
...@@ -4,8 +4,14 @@ ...@@ -4,8 +4,14 @@
#import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h" #import "ios/chrome/browser/ui/popup_menu/cells/popup_menu_tools_item.h"
#include <stdlib.h>
#include "base/logging.h" #include "base/logging.h"
#import "ios/chrome/browser/ui/reading_list/number_badge_view.h"
#import "ios/chrome/browser/ui/reading_list/text_badge_view.h"
#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
#import "ios/chrome/browser/ui/util/constraints_ui_util.h" #import "ios/chrome/browser/ui/util/constraints_ui_util.h"
#import "ios/chrome/common/material_timing.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support." #error "This file requires ARC support."
...@@ -14,14 +20,17 @@ ...@@ -14,14 +20,17 @@
namespace { namespace {
const CGFloat kImageLength = 28; const CGFloat kImageLength = 28;
const CGFloat kCellHeight = 44; const CGFloat kCellHeight = 44;
const CGFloat kImageTextMargin = 11; const CGFloat kInnerMargin = 11;
const CGFloat kMargin = 15; const CGFloat kMargin = 15;
const CGFloat kImageTopMargin = 8; const CGFloat kTopMargin = 8;
const CGFloat kTopMarginBadge = 14;
} }
@implementation PopupMenuToolsItem @implementation PopupMenuToolsItem
@synthesize actionIdentifier = _actionIdentifier; @synthesize actionIdentifier = _actionIdentifier;
@synthesize badgeNumber = _badgeNumber;
@synthesize badgeText = _badgeText;
@synthesize image = _image; @synthesize image = _image;
@synthesize title = _title; @synthesize title = _title;
@synthesize enabled = _enabled; @synthesize enabled = _enabled;
...@@ -41,12 +50,25 @@ const CGFloat kImageTopMargin = 8; ...@@ -41,12 +50,25 @@ const CGFloat kImageTopMargin = 8;
cell.titleLabel.text = self.title; cell.titleLabel.text = self.title;
cell.imageView.image = self.image; cell.imageView.image = self.image;
cell.userInteractionEnabled = self.enabled; cell.userInteractionEnabled = self.enabled;
[cell setBadgeNumber:self.badgeNumber];
[cell setBadgeText:self.badgeText];
} }
#pragma mark - PopupMenuItem #pragma mark - PopupMenuItem
- (CGSize)cellSizeForWidth:(CGFloat)width { - (CGSize)cellSizeForWidth:(CGFloat)width {
return [self.cellClass sizeForWidth:width title:self.title]; // TODO(crbug.com/828357): This should be done at the table view level.
static PopupMenuToolsCell* cell;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cell = [[PopupMenuToolsCell alloc] init];
});
[self configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
cell.frame = CGRectMake(0, 0, width, 0);
[cell setNeedsLayout];
[cell layoutIfNeeded];
return [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
} }
@end @end
...@@ -59,13 +81,21 @@ const CGFloat kImageTopMargin = 8; ...@@ -59,13 +81,21 @@ const CGFloat kImageTopMargin = 8;
@property(nonatomic, strong, readwrite) UILabel* titleLabel; @property(nonatomic, strong, readwrite) UILabel* titleLabel;
// Image view for the cell, redefined as readwrite. // Image view for the cell, redefined as readwrite.
@property(nonatomic, strong, readwrite) UIImageView* imageView; @property(nonatomic, strong, readwrite) UIImageView* imageView;
// Badge displaying a number.
@property(nonatomic, strong) NumberBadgeView* numberBadgeView;
// Badge displaying text.
@property(nonatomic, strong) TextBadgeView* textBadgeView;
// Constraints between the trailing of the label and the badges.
@property(nonatomic, strong) NSLayoutConstraint* titleToBadgeConstraint;
@end @end
@implementation PopupMenuToolsCell @implementation PopupMenuToolsCell
@synthesize imageView = _imageView; @synthesize imageView = _imageView;
@synthesize numberBadgeView = _numberBadgeView;
@synthesize textBadgeView = _textBadgeView;
@synthesize titleLabel = _titleLabel; @synthesize titleLabel = _titleLabel;
@synthesize titleToBadgeConstraint = _titleToBadgeConstraint;
- (instancetype)initWithStyle:(UITableViewCellStyle)style - (instancetype)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString*)reuseIdentifier { reuseIdentifier:(NSString*)reuseIdentifier {
...@@ -74,53 +104,130 @@ const CGFloat kImageTopMargin = 8; ...@@ -74,53 +104,130 @@ const CGFloat kImageTopMargin = 8;
_titleLabel = [[UILabel alloc] init]; _titleLabel = [[UILabel alloc] init];
_titleLabel.numberOfLines = 0; _titleLabel.numberOfLines = 0;
_titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; _titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
[_titleLabel
setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
forAxis:
UILayoutConstraintAxisHorizontal];
[_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultLow - 1
forAxis:UILayoutConstraintAxisHorizontal];
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO; _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
_imageView = [[UIImageView alloc] init]; _imageView = [[UIImageView alloc] init];
_imageView.translatesAutoresizingMaskIntoConstraints = NO; _imageView.translatesAutoresizingMaskIntoConstraints = NO;
_numberBadgeView = [[NumberBadgeView alloc] init];
_numberBadgeView.translatesAutoresizingMaskIntoConstraints = NO;
_textBadgeView = [[TextBadgeView alloc] initWithText:nil];
_textBadgeView.translatesAutoresizingMaskIntoConstraints = NO;
_textBadgeView.hidden = YES;
[self.contentView addSubview:_titleLabel]; [self.contentView addSubview:_titleLabel];
[self.contentView addSubview:_imageView]; [self.contentView addSubview:_imageView];
[self.contentView addSubview:_numberBadgeView];
[self.contentView addSubview:_textBadgeView];
ApplyVisualConstraintsWithMetrics( ApplyVisualConstraintsWithMetrics(
@[ @[
@"H:|-(margin)-[image(imageSize)]-(textImage)-[text]-(margin)-|", @"H:|-(margin)-[image(imageLength)]-(innerMargin)-[label]",
@"V:|-(imageTopMargin)-[image(imageSize)]", @"V:|[text]|" @"H:[numberBadge]-(margin)-|", @"H:[textBadge]-(margin)-|",
@"V:|-(topMargin)-[image(imageLength)]",
@"V:|-(topMarginBadge)-[numberBadge]",
@"V:|-(topMarginBadge)-[textBadge]",
@"V:|-(topMargin)-[label]-(topMargin)-|"
], ],
@{@"image" : _imageView, @"text" : _titleLabel}, @{ @{
@"image" : _imageView,
@"label" : _titleLabel,
@"numberBadge" : _numberBadgeView,
@"textBadge" : _textBadgeView
},
@{
@"margin" : @(kMargin), @"margin" : @(kMargin),
@"imageSize" : @(kImageLength), @"innerMargin" : @(kInnerMargin),
@"textImage" : @(kImageTextMargin), @"topMargin" : @(kTopMargin),
@"imageTopMargin" : @(kImageTopMargin), @"topMarginBadge" : @(kTopMarginBadge),
@"imageLength" : @(kImageLength),
}); });
[self.contentView.heightAnchor [self.contentView.heightAnchor
constraintGreaterThanOrEqualToConstant:kCellHeight] constraintGreaterThanOrEqualToConstant:kCellHeight]
.active = YES; .active = YES;
NSLayoutConstraint* trailingEdge = [_titleLabel.trailingAnchor
constraintEqualToAnchor:self.contentView.trailingAnchor
constant:-kMargin];
trailingEdge.priority = UILayoutPriorityDefaultHigh - 2;
trailingEdge.active = YES;
} }
return self; return self;
} }
+ (CGSize)sizeForWidth:(CGFloat)width title:(NSString*)title { - (void)setBadgeNumber:(NSInteger)badgeNumber {
// This is not using a prototype cell and autolayout for performance reasons. BOOL wasHidden = self.numberBadgeView.hidden;
CGFloat nonTitleElementWidth = kImageLength + 2 * kMargin + kImageTextMargin; [self.numberBadgeView setNumber:badgeNumber animated:YES];
// The width should be enough to contain more than the image. // If the number badge is shown, then the text badge must be hidden.
DCHECK(width > nonTitleElementWidth); if (!self.numberBadgeView.hidden && !self.textBadgeView.hidden) {
[self setBadgeText:nil];
CGSize titleSize = CGSizeMake(width - nonTitleElementWidth, }
[UIScreen mainScreen].bounds.size.height); if (!self.numberBadgeView.hidden && wasHidden) {
NSDictionary* attributes = @{NSFontAttributeName : [self cellFont]}; self.titleToBadgeConstraint.active = NO;
CGRect rectForString = self.titleToBadgeConstraint = [self.numberBadgeView.leadingAnchor
[title boundingRectWithSize:titleSize constraintGreaterThanOrEqualToAnchor:self.titleLabel.trailingAnchor
options:NSStringDrawingUsesLineFragmentOrigin constant:kInnerMargin];
attributes:attributes self.titleToBadgeConstraint.active = YES;
context:nil]; } else if (self.numberBadgeView.hidden && !wasHidden) {
CGSize size = rectForString.size; self.titleToBadgeConstraint.active = NO;
size.height = MAX(size.height, kCellHeight); }
size.width += nonTitleElementWidth; }
return size;
- (void)setBadgeText:(NSString*)badgeText {
// Only 1 badge can be visible at a time, and the number badge takes priority.
if (badgeText && !self.numberBadgeView.isHidden) {
return;
}
if (badgeText) {
[self.textBadgeView setText:badgeText];
if (self.textBadgeView.hidden) {
self.textBadgeView.hidden = NO;
self.titleToBadgeConstraint.active = NO;
self.titleToBadgeConstraint = [self.textBadgeView.leadingAnchor
constraintGreaterThanOrEqualToAnchor:self.titleLabel.trailingAnchor
constant:kInnerMargin];
self.titleToBadgeConstraint.active = YES;
self.textBadgeView.alpha = 1;
}
} else if (!self.textBadgeView.hidden) {
self.textBadgeView.hidden = YES;
self.titleToBadgeConstraint.active = NO;
}
}
- (void)layoutSubviews {
[super layoutSubviews];
// Adjust the text label preferredMaxLayoutWidth when the parent's width
// changes, for instance on screen rotation.
CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
CGFloat trailingMargin = kMargin;
if (!self.numberBadgeView.hidden) {
trailingMargin += self.numberBadgeView.bounds.size.width + kInnerMargin;
} else if (!self.textBadgeView.hidden) {
trailingMargin += self.textBadgeView.bounds.size.width + kInnerMargin;
}
CGFloat leadingMargin = kMargin + kImageLength + kInnerMargin;
self.titleLabel.preferredMaxLayoutWidth =
parentWidth - leadingMargin - trailingMargin;
// Re-layout with the new preferred width to allow the label to adjust its
// height.
[super layoutSubviews];
} }
#pragma mark - UITableViewCell
- (void)prepareForReuse { - (void)prepareForReuse {
[super prepareForReuse]; [super prepareForReuse];
self.userInteractionEnabled = YES; self.userInteractionEnabled = YES;
...@@ -139,18 +246,6 @@ const CGFloat kImageTopMargin = 8; ...@@ -139,18 +246,6 @@ const CGFloat kImageTopMargin = 8;
#pragma mark - Private #pragma mark - Private
// Returns the font used by this cell's label.
+ (UIFont*)cellFont {
static UIFont* font;
if (!font) {
PopupMenuToolsCell* cell =
[[PopupMenuToolsCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"fakeID"];
font = cell.titleLabel.font;
}
return font;
}
// Returns the color of the disabled button's title. // Returns the color of the disabled button's title.
+ (UIColor*)disabledColor { + (UIColor*)disabledColor {
static UIColor* systemTintColorForDisabled = nil; static UIColor* systemTintColorForDisabled = nil;
......
...@@ -77,6 +77,7 @@ const CGFloat kLabelMargin = 2.5f; ...@@ -77,6 +77,7 @@ const CGFloat kLabelMargin = 2.5f;
} else { } else {
[self.textBadge setText:[NSString stringWithFormat:@"%" PRIdNS, number]]; [self.textBadge setText:[NSString stringWithFormat:@"%" PRIdNS, number]];
self.hidden = (number > 0 ? NO : YES); self.hidden = (number > 0 ? NO : YES);
self.alpha = (number > 0 ? 1 : 0);
} }
} }
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "base/logging.h" #include "base/logging.h"
#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
#include "ios/chrome/browser/ui/ui_util.h"
#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -13,7 +14,8 @@ ...@@ -13,7 +14,8 @@
#endif #endif
namespace { namespace {
const CGFloat kFontSize = 10.0f; const CGFloat kFontSize = 11.0f;
const CGFloat kLegacyFontSize = 10.0f;
// The margin between the top and bottom of the label and the badge. // The margin between the top and bottom of the label and the badge.
const CGFloat kLabelVerticalMargin = 2.5f; const CGFloat kLabelVerticalMargin = 2.5f;
// The default value for the margin between the sides of the label and the // The default value for the margin between the sides of the label and the
...@@ -61,7 +63,14 @@ const CGFloat kDefaultLabelHorizontalMargin = 8.5f; ...@@ -61,7 +63,14 @@ const CGFloat kDefaultLabelHorizontalMargin = 8.5f;
[self addSubview:self.label]; [self addSubview:self.label];
self.didAddSubviews = YES; self.didAddSubviews = YES;
[self activateConstraints]; [self activateConstraints];
[self setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]]; if (IsUIRefreshPhase1Enabled()) {
[self setBackgroundColor:[UIColor colorWithRed:0.101
green:0.45
blue:0.909
alpha:0.1]];
} else {
[self setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]];
}
[self setAccessibilityLabel:self.label.text]; [self setAccessibilityLabel:self.label.text];
} }
[super willMoveToSuperview:newSuperview]; [super willMoveToSuperview:newSuperview];
...@@ -90,9 +99,18 @@ const CGFloat kDefaultLabelHorizontalMargin = 8.5f; ...@@ -90,9 +99,18 @@ const CGFloat kDefaultLabelHorizontalMargin = 8.5f;
// Return a label that displays text in white with center alignment. // Return a label that displays text in white with center alignment.
+ (UILabel*)labelWithText:(NSString*)text { + (UILabel*)labelWithText:(NSString*)text {
UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setFont:[[MDCTypography fontLoader] boldFontOfSize:kFontSize]]; if (IsUIRefreshPhase1Enabled()) {
[label setFont:[UIFont systemFontOfSize:kFontSize
weight:UIFontWeightSemibold]];
[label setTextColor:[UIColor colorWithRed:0.101
green:0.45
blue:0.909
alpha:1]];
} else {
[label setFont:[[MDCTypography fontLoader] boldFontOfSize:kLegacyFontSize]];
[label setTextColor:[UIColor whiteColor]];
}
[label setTranslatesAutoresizingMaskIntoConstraints:NO]; [label setTranslatesAutoresizingMaskIntoConstraints:NO];
[label setTextColor:[UIColor whiteColor]];
[label setText:text]; [label setText:text];
[label setTextAlignment:NSTextAlignmentCenter]; [label setTextAlignment:NSTextAlignmentCenter];
return label; return label;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment