Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(414)

Side by Side Diff: ios/chrome/browser/ui/toolbar/keyboard_accessory_view.mm

Issue 2934463002: [iOS] Add experimental new keyboard accessory view. (Closed)
Patch Set: Addressed comments. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view.h" 5 #import "ios/chrome/browser/ui/toolbar/keyboard_accessory_view.h"
6 6
7 #import <NotificationCenter/NotificationCenter.h>
8
7 #include "base/mac/foundation_util.h" 9 #include "base/mac/foundation_util.h"
10 #include "ios/chrome/browser/experimental_flags.h"
8 #include "ios/chrome/browser/ui/commands/ios_command_ids.h" 11 #include "ios/chrome/browser/ui/commands/ios_command_ids.h"
12 #import "ios/chrome/browser/ui/fancy_ui/colored_button.h"
13 #include "ios/chrome/browser/ui/rtl_geometry.h"
9 #include "ios/chrome/browser/ui/ui_util.h" 14 #include "ios/chrome/browser/ui/ui_util.h"
10 #import "ios/chrome/browser/ui/uikit_ui_util.h" 15 #import "ios/chrome/browser/ui/uikit_ui_util.h"
11 #include "ios/chrome/grit/ios_strings.h" 16 #include "ios/chrome/grit/ios_strings.h"
12 17
13 #if !defined(__has_feature) || !__has_feature(objc_arc) 18 #if !defined(__has_feature) || !__has_feature(objc_arc)
14 #error "This file requires ARC support." 19 #error "This file requires ARC support."
15 #endif 20 #endif
16 21
17 @interface KeyboardAccessoryView () 22 @interface KeyboardAccessoryView ()
18 23
19 @property(nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate; 24 @property(nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate;
20 @property(nonatomic, retain) UIButton* voiceSearchButton; 25 @property(nonatomic, retain) UIButton* voiceSearchButton;
21 26
22 // Creates a button with the same appearance as a keyboard key. 27 // Creates a button with the same appearance as a keyboard key.
23 - (UIView*)keyboardButtonWithTitle:(NSString*)title frame:(CGRect)frame; 28 - (UIView*)keyboardButtonWithTitle:(NSString*)title frame:(CGRect)frame;
29 // Creates a button shortcut for |title|.
30 - (UIView*)shortcutButtonWithTitle:(NSString*)title;
31 // Creates a button with an icon based on |iconName|.
32 - (UIButton*)iconButton:(NSString*)iconName;
24 // Called when a keyboard shortcut button is pressed. 33 // Called when a keyboard shortcut button is pressed.
25 - (void)keyboardButtonPressed:(NSString*)title; 34 - (void)keyboardButtonPressed:(NSString*)title;
26 35
27 @end 36 @end
28 37
29 @implementation KeyboardAccessoryView 38 @implementation KeyboardAccessoryView
30 39
31 @synthesize mode = _mode; 40 @synthesize mode = _mode;
32 @synthesize delegate = _delegate; 41 @synthesize delegate = _delegate;
33 @synthesize voiceSearchButton = _voiceSearchButton; 42 @synthesize voiceSearchButton = _voiceSearchButton;
34 43
35 - (instancetype)initWithButtons:(NSArray<NSString*>*)buttonTitles 44 - (instancetype)initWithButtons:(NSArray<NSString*>*)buttonTitles
36 delegate:(id<KeyboardAccessoryViewDelegate>)delegate { 45 delegate:(id<KeyboardAccessoryViewDelegate>)delegate {
37 const CGFloat kViewHeight = 70.0; 46 const CGFloat kViewHeight = 70.0;
38 const CGFloat kViewHeightCompact = 43.0; 47 const CGFloat kViewHeightCompact = 43.0;
48 const BOOL isCompact = IsCompact();
49
50 CGFloat width = [[UIScreen mainScreen] bounds].size.width;
51 CGFloat height = isCompact ? kViewHeightCompact : kViewHeight;
52 CGRect frame = CGRectMake(0.0, 0.0, width, height);
53
54 self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard];
55 if (self) {
56 _delegate = delegate;
57 if (experimental_flags::IsKeyboardAccessoryViewWithCameraSearchEnabled()) {
58 [self newAccessoryInitialization:buttonTitles];
59 } else {
60 [self accessoryInitialization:buttonTitles];
61 }
62 }
63 return self;
64 }
65
66 - (void)newAccessoryInitialization:(NSArray<NSString*>*)buttonTitles {
gambard 2017/06/09 13:30:51 I know I suggested the name and it is returning vo
gambard 2017/06/09 13:30:51 Comment for the method
jif 2017/06/09 15:15:24 facepalm. Done.
jif 2017/06/09 15:15:24 Done.
67 const CGFloat kButtonMinSizeX = 61.0;
68 const CGFloat kButtonMinSizeXCompact = 32.0;
69 const CGFloat kButtonSizeY = 62.0;
70 const CGFloat kButtonSizeYCompact = 30.0;
71 const CGFloat kBetweenButtonSpacing = 15.0;
72 const CGFloat kBetweenButtonSpacingCompact = 6.0;
73 const CGFloat kSeparatorAlpha = 0.1;
74 const BOOL isCompact = IsCompact();
75
76 // Create and add stackview filled with the shortcut buttons.
77 UIStackView* stackView = [[UIStackView alloc] init];
78 [stackView setTranslatesAutoresizingMaskIntoConstraints:NO];
79 stackView.spacing =
80 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing;
81 for (NSString* title in buttonTitles) {
82 UIView* button = [self shortcutButtonWithTitle:title];
83 [button setTranslatesAutoresizingMaskIntoConstraints:NO];
84 CGFloat buttonMinWidth =
85 isCompact ? kButtonMinSizeXCompact : kButtonMinSizeX;
86 [button.widthAnchor constraintGreaterThanOrEqualToConstant:buttonMinWidth]
87 .active = YES;
88 CGFloat buttonHeight = isCompact ? kButtonSizeYCompact : kButtonSizeY;
89 [button.heightAnchor constraintEqualToConstant:buttonHeight].active = YES;
90 [stackView addArrangedSubview:button];
91 }
92 [self addSubview:stackView];
93
94 // Create and add buttons for voice and camera search.
95 UIButton* cameraButton = [self iconButton:@"qr_scanner_keyboard_accessory"];
96 [cameraButton addTarget:_delegate
97 action:@selector(keyboardAccessoryCameraSearchTouchUpInside)
98 forControlEvents:UIControlEventTouchUpInside];
99 [self addSubview:cameraButton];
100
101 _voiceSearchButton = [self iconButton:@"voice_icon_keyboard_accessory"];
102 [self addSubview:_voiceSearchButton];
103 [_voiceSearchButton addTarget:_delegate
104 action:@selector(keyboardAccessoryVoiceSearchTouchDown)
105 forControlEvents:UIControlEventTouchDown];
106 [_voiceSearchButton
107 addTarget:_delegate
108 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside)
109 forControlEvents:UIControlEventTouchUpInside];
110
111 // Create and add 1 pixel high separator view.
112 UIView* separator = [[UIView alloc] init];
113 [separator setTranslatesAutoresizingMaskIntoConstraints:NO];
114 [separator
115 setBackgroundColor:[UIColor colorWithWhite:0 alpha:kSeparatorAlpha]];
116 [separator.heightAnchor
117 constraintEqualToConstant:1.0 / [[UIScreen mainScreen] scale]]
118 .active = YES;
119 [self addSubview:separator];
120
121 // Position all the views.
122 NSDictionary* viewsDictionary = @{
123 @"cameraButton" : cameraButton,
124 @"voiceSearch" : _voiceSearchButton,
125 @"stackView" : stackView,
126 @"separator" : separator,
127 };
128 NSArray* constraints = @[
129 @"H:|-8-[cameraButton]-8-[voiceSearch]-(>=16)-[stackView]",
130 @"H:|-0-[separator]-0-|",
131 @"V:[separator]-0-|",
132 ];
133 ApplyVisualConstraintsWithOptions(constraints, viewsDictionary,
134 LayoutOptionForRTLSupport(), self);
135 AddSameCenterYConstraint(self, cameraButton);
136 AddSameCenterYConstraint(self, _voiceSearchButton);
137 AddSameCenterYConstraint(self, stackView);
138 // The following constraint is supposed to break if there's not enough
139 // space to center the stack view.
140 NSLayoutConstraint* horizontallyCenterStackViewConstraint =
141 [self.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor];
142 horizontallyCenterStackViewConstraint.priority = UILayoutPriorityDefaultHigh;
143 horizontallyCenterStackViewConstraint.active = YES;
144 }
145
146 - (void)accessoryInitialization:(NSArray<NSString*>*)buttonTitles {
gambard 2017/06/09 13:30:51 Comment for the method.
39 const CGFloat kButtonInset = 5.0; 147 const CGFloat kButtonInset = 5.0;
40 const CGFloat kButtonSizeX = 61.0; 148 const CGFloat kButtonSizeX = 61.0;
41 const CGFloat kButtonSizeXCompact = 46.0; 149 const CGFloat kButtonSizeXCompact = 46.0;
42 const CGFloat kButtonSizeY = 62.0; 150 const CGFloat kButtonSizeY = 62.0;
43 const CGFloat kButtonSizeYCompact = 35.0; 151 const CGFloat kButtonSizeYCompact = 35.0;
44 const CGFloat kBetweenButtonSpacing = 15.0; 152 const CGFloat kBetweenButtonSpacing = 15.0;
45 const CGFloat kBetweenButtonSpacingCompact = 7.0; 153 const CGFloat kBetweenButtonSpacingCompact = 7.0;
46 const BOOL isCompact = IsCompact(); 154 const BOOL isCompact = IsCompact();
47 155
48 CGFloat width = [[UIScreen mainScreen] bounds].size.width; 156 // Center buttons in available space by placing them within a parent view
49 CGFloat height = isCompact ? kViewHeightCompact : kViewHeight; 157 // that auto-centers.
50 CGRect frame = CGRectMake(0.0, 0.0, width, height); 158 CGFloat betweenButtonSpacing =
159 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing;
160 const CGFloat buttonWidth = isCompact ? kButtonSizeXCompact : kButtonSizeX;
51 161
52 self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard]; 162 CGFloat totalWidth = (buttonTitles.count * buttonWidth) +
53 if (self) { 163 ((buttonTitles.count - 1) * betweenButtonSpacing);
54 _delegate = delegate; 164 CGFloat indent = floor((self.frame.size.width - totalWidth) / 2.0);
165 if (indent < kButtonInset)
166 indent = kButtonInset;
167 CGRect parentViewRect =
168 CGRectMake(indent, 0.0, totalWidth, self.frame.size.height);
169 UIView* parentView = [[UIView alloc] initWithFrame:parentViewRect];
170 [parentView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
171 UIViewAutoresizingFlexibleRightMargin];
172 [self addSubview:parentView];
55 173
56 // Center buttons in available space by placing them within a parent view 174 // Create the shortcut buttons, starting at the left edge of |parentView|.
57 // that auto-centers. 175 CGRect currentFrame =
58 CGFloat betweenButtonSpacing = 176 CGRectMake(0.0, kButtonInset, buttonWidth,
59 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing; 177 isCompact ? kButtonSizeYCompact : kButtonSizeY);
60 const CGFloat buttonWidth = isCompact ? kButtonSizeXCompact : kButtonSizeX;
61 178
62 CGFloat totalWidth = (buttonTitles.count * buttonWidth) + 179 for (NSString* title in buttonTitles) {
63 ((buttonTitles.count - 1) * betweenButtonSpacing); 180 UIView* button = [self keyboardButtonWithTitle:title frame:currentFrame];
64 CGFloat indent = floor((width - totalWidth) / 2.0); 181 [parentView addSubview:button];
65 if (indent < kButtonInset) 182 currentFrame.origin.x = CGRectGetMaxX(currentFrame) + betweenButtonSpacing;
66 indent = kButtonInset;
67 CGRect parentViewRect = CGRectMake(indent, 0.0, totalWidth, height);
68 UIView* parentView = [[UIView alloc] initWithFrame:parentViewRect];
69 [parentView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
70 UIViewAutoresizingFlexibleRightMargin];
71 [self addSubview:parentView];
72
73 // Create the shortcut buttons, starting at the left edge of |parentView|.
74 CGRect currentFrame =
75 CGRectMake(0.0, kButtonInset, buttonWidth,
76 isCompact ? kButtonSizeYCompact : kButtonSizeY);
77
78 for (NSString* title in buttonTitles) {
79 UIView* button = [self keyboardButtonWithTitle:title frame:currentFrame];
80 [parentView addSubview:button];
81 currentFrame.origin.x =
82 CGRectGetMaxX(currentFrame) + betweenButtonSpacing;
83 }
84
85 // Create the voice search button and add it over the text buttons.
86 _voiceSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
87 [_voiceSearchButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
88 SetA11yLabelAndUiAutomationName(
89 _voiceSearchButton, IDS_IOS_ACCNAME_VOICE_SEARCH, @"Voice Search");
90 UIImage* voiceRow = [UIImage imageNamed:@"custom_row_voice"];
91 UIImage* voiceRowPressed = [UIImage imageNamed:@"custom_row_voice_pressed"];
92 [_voiceSearchButton setBackgroundImage:voiceRow
93 forState:UIControlStateNormal];
94 [_voiceSearchButton setBackgroundImage:voiceRowPressed
95 forState:UIControlStateHighlighted];
96
97 UIImage* voiceIcon = [UIImage imageNamed:@"voice_icon_keyboard_accessory"];
98 [_voiceSearchButton setAdjustsImageWhenHighlighted:NO];
99 [_voiceSearchButton setImage:voiceIcon forState:UIControlStateNormal];
100 [_voiceSearchButton setFrame:[self bounds]];
101
102 [_voiceSearchButton
103 addTarget:delegate
104 action:@selector(keyboardAccessoryVoiceSearchTouchDown)
105 forControlEvents:UIControlEventTouchDown];
106 [_voiceSearchButton
107 addTarget:delegate
108 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside)
109 forControlEvents:UIControlEventTouchUpInside];
110 [self addSubview:_voiceSearchButton];
111 } 183 }
112 184
113 return self; 185 // Create the voice search button and add it over the text buttons.
186 _voiceSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
187 [_voiceSearchButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
188 SetA11yLabelAndUiAutomationName(
189 _voiceSearchButton, IDS_IOS_ACCNAME_VOICE_SEARCH, @"Voice Search");
190 UIImage* voiceRow = [UIImage imageNamed:@"custom_row_voice"];
191 UIImage* voiceRowPressed = [UIImage imageNamed:@"custom_row_voice_pressed"];
192 [_voiceSearchButton setBackgroundImage:voiceRow
193 forState:UIControlStateNormal];
194 [_voiceSearchButton setBackgroundImage:voiceRowPressed
195 forState:UIControlStateHighlighted];
196
197 UIImage* voiceIcon = [UIImage imageNamed:@"voice_icon_keyboard_accessory"];
198 [_voiceSearchButton setAdjustsImageWhenHighlighted:NO];
199 [_voiceSearchButton setImage:voiceIcon forState:UIControlStateNormal];
200 [_voiceSearchButton setFrame:[self bounds]];
201 [_voiceSearchButton addTarget:_delegate
202 action:@selector(keyboardAccessoryVoiceSearchTouchDown)
203 forControlEvents:UIControlEventTouchDown];
204 [_voiceSearchButton
205 addTarget:_delegate
206 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside)
207 forControlEvents:UIControlEventTouchUpInside];
208 [self addSubview:_voiceSearchButton];
114 } 209 }
115 210
116 - (void)setMode:(KeyboardAccessoryViewMode)mode { 211 - (void)setMode:(KeyboardAccessoryViewMode)mode {
212 if (experimental_flags::IsKeyboardAccessoryViewWithCameraSearchEnabled()) {
213 return;
214 }
117 _mode = mode; 215 _mode = mode;
118 switch (mode) { 216 switch (mode) {
119 case VOICE_SEARCH: 217 case VOICE_SEARCH:
120 [_voiceSearchButton setHidden:NO]; 218 [_voiceSearchButton setHidden:NO];
121 break; 219 break;
122 case KEY_SHORTCUTS: 220 case KEY_SHORTCUTS:
123 [_voiceSearchButton setHidden:YES]; 221 [_voiceSearchButton setHidden:YES];
124 break; 222 break;
125 } 223 }
126 } 224 }
(...skipping 18 matching lines...) Expand all
145 [button.titleLabel setFont:font]; 243 [button.titleLabel setFont:font];
146 [button setBackgroundImage:backgroundImage forState:UIControlStateNormal]; 244 [button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
147 [button addTarget:self 245 [button addTarget:self
148 action:@selector(keyboardButtonPressed:) 246 action:@selector(keyboardButtonPressed:)
149 forControlEvents:UIControlEventTouchUpInside]; 247 forControlEvents:UIControlEventTouchUpInside];
150 button.isAccessibilityElement = YES; 248 button.isAccessibilityElement = YES;
151 [button setAccessibilityLabel:title]; 249 [button setAccessibilityLabel:title];
152 return button; 250 return button;
153 } 251 }
154 252
253 - (UIView*)shortcutButtonWithTitle:(NSString*)title {
254 const CGFloat kCornerRadius = 4.0;
255 const CGFloat kAlphaStateNormal = 0.1;
256 const CGFloat kAlphaStateHighlighted = 0.2;
257 const CGFloat kHorizontalEdgeInset = 8;
258 const CGFloat kIpadButtonTitleFontSize = 20.0;
259 const CGFloat kIphoneButtonTitleFontSize = 15.0;
260
261 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom];
262 UIFont* font = nil;
263
264 [button setTitle:title forState:UIControlStateNormal];
265 [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
266
267 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateNormal)
268 forState:UIControlStateNormal];
269 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateHighlighted)
270 forState:UIControlStateHighlighted];
271
272 button.layer.cornerRadius = kCornerRadius;
273 button.contentEdgeInsets =
274 UIEdgeInsetsMake(0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset);
275 button.clipsToBounds = YES;
276
277 if (IsIPadIdiom()) {
278 font = GetUIFont(FONT_HELVETICA, false, kIpadButtonTitleFontSize);
279 } else {
280 font = GetUIFont(FONT_HELVETICA, true, kIphoneButtonTitleFontSize);
281 }
282
283 [button.titleLabel setFont:font];
284
285 [button addTarget:self
286 action:@selector(keyboardButtonPressed:)
287 forControlEvents:UIControlEventTouchUpInside];
288 button.isAccessibilityElement = YES;
289 [button setAccessibilityLabel:title];
290 return button;
291 }
292
293 - (UIButton*)iconButton:(NSString*)iconName {
294 const CGFloat kIconTintAlphaStateNormal = 0.45;
295 const CGFloat kIconTintAlphaStateHighlighted = 0.6;
296
297 UIColor* iconTintStateNormal = UIColorFromRGB(0, kIconTintAlphaStateNormal);
298 UIColor* iconTintStateHighlighted =
299 UIColorFromRGB(0, kIconTintAlphaStateHighlighted);
300
301 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom];
302
303 [button setTintColor:iconTintStateNormal forState:UIControlStateNormal];
304 [button setTintColor:iconTintStateHighlighted
305 forState:UIControlStateHighlighted];
306 [button setTranslatesAutoresizingMaskIntoConstraints:NO];
307 UIImage* icon = [[UIImage imageNamed:iconName]
308 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
309 [button setImage:icon forState:UIControlStateNormal];
310 return button;
311 }
312
155 - (BOOL)enableInputClicksWhenVisible { 313 - (BOOL)enableInputClicksWhenVisible {
156 return YES; 314 return YES;
157 } 315 }
158 316
159 - (void)keyboardButtonPressed:(id)sender { 317 - (void)keyboardButtonPressed:(id)sender {
160 UIButton* button = base::mac::ObjCCastStrict<UIButton>(sender); 318 UIButton* button = base::mac::ObjCCastStrict<UIButton>(sender);
161 [[UIDevice currentDevice] playInputClick]; 319 [[UIDevice currentDevice] playInputClick];
162 [_delegate keyPressed:[button currentTitle]]; 320 [_delegate keyPressed:[button currentTitle]];
163 } 321 }
164 322
165 @end 323 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698