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

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: 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*)newShortcutButtonWithTitle:(NSString*)title;
31 // Creates a button with an icon based on |iconName|.
32 - (UIButton*)newIconButton:(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;
39 const CGFloat kButtonInset = 5.0;
40 const CGFloat kButtonSizeX = 61.0;
41 const CGFloat kButtonSizeXCompact = 46.0;
42 const CGFloat kButtonSizeY = 62.0;
43 const CGFloat kButtonSizeYCompact = 35.0;
44 const CGFloat kBetweenButtonSpacing = 15.0;
45 const CGFloat kBetweenButtonSpacingCompact = 7.0;
46 const BOOL isCompact = IsCompact(); 48 const BOOL isCompact = IsCompact();
47 49
48 CGFloat width = [[UIScreen mainScreen] bounds].size.width; 50 CGFloat width = [[UIScreen mainScreen] bounds].size.width;
49 CGFloat height = isCompact ? kViewHeightCompact : kViewHeight; 51 CGFloat height = isCompact ? kViewHeightCompact : kViewHeight;
50 CGRect frame = CGRectMake(0.0, 0.0, width, height); 52 CGRect frame = CGRectMake(0.0, 0.0, width, height);
51 53
52 self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard]; 54 self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard];
53 if (self) { 55 if (self) {
54 _delegate = delegate; 56 _delegate = delegate;
57 if (experimental_flags::IsNewKeyboardAccessoryViewEnabled()) {
gambard 2017/06/09 12:35:42 This is a >160 lines methods. Maybe we can split i
jif 2017/06/09 13:19:37 Done.
58 const CGFloat kButtonMinSizeX = 61.0;
59 const CGFloat kButtonMinSizeXCompact = 32.0;
60 const CGFloat kButtonSizeY = 62.0;
61 const CGFloat kButtonSizeYCompact = 30.0;
62 const CGFloat kBetweenButtonSpacing = 15.0;
63 const CGFloat kBetweenButtonSpacingCompact = 6.0;
64 const CGFloat kSeparatorAlpha = 0.1;
55 65
56 // Center buttons in available space by placing them within a parent view 66 // Create stackview filled with the shortcut buttons
57 // that auto-centers. 67 UIStackView* stackView = [[UIStackView alloc] init];
58 CGFloat betweenButtonSpacing = 68 [stackView setTranslatesAutoresizingMaskIntoConstraints:NO];
59 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing; 69 stackView.spacing =
60 const CGFloat buttonWidth = isCompact ? kButtonSizeXCompact : kButtonSizeX; 70 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing;
71 for (NSString* title in buttonTitles) {
72 UIView* button = [self newShortcutButtonWithTitle:title];
73 [button setTranslatesAutoresizingMaskIntoConstraints:NO];
74 CGFloat buttonMinWidth =
75 isCompact ? kButtonMinSizeXCompact : kButtonMinSizeX;
76 [button.widthAnchor
77 constraintGreaterThanOrEqualToConstant:buttonMinWidth]
78 .active = YES;
79 CGFloat buttonHeight = isCompact ? kButtonSizeYCompact : kButtonSizeY;
80 [button.heightAnchor constraintEqualToConstant:buttonHeight].active =
81 YES;
82 [stackView addArrangedSubview:button];
83 }
84 [self addSubview:stackView];
61 85
62 CGFloat totalWidth = (buttonTitles.count * buttonWidth) + 86 // Create and add image for camera search.
63 ((buttonTitles.count - 1) * betweenButtonSpacing); 87 UIButton* cameraButton =
64 CGFloat indent = floor((width - totalWidth) / 2.0); 88 [self newIconButton:@"qr_scanner_keyboard_accessory"];
65 if (indent < kButtonInset) 89 [cameraButton
66 indent = kButtonInset; 90 addTarget:delegate
67 CGRect parentViewRect = CGRectMake(indent, 0.0, totalWidth, height); 91 action:@selector(keyboardAccessoryCameraSearchTouchUpInside)
68 UIView* parentView = [[UIView alloc] initWithFrame:parentViewRect]; 92 forControlEvents:UIControlEventTouchUpInside];
69 [parentView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | 93 [self addSubview:cameraButton];
70 UIViewAutoresizingFlexibleRightMargin];
71 [self addSubview:parentView];
72 94
73 // Create the shortcut buttons, starting at the left edge of |parentView|. 95 _voiceSearchButton =
74 CGRect currentFrame = 96 [self newIconButton:@"voice_icon_keyboard_accessory"];
75 CGRectMake(0.0, kButtonInset, buttonWidth, 97 [self addSubview:_voiceSearchButton];
76 isCompact ? kButtonSizeYCompact : kButtonSizeY); 98 [_voiceSearchButton
99 addTarget:delegate
100 action:@selector(keyboardAccessoryVoiceSearchTouchDown)
101 forControlEvents:UIControlEventTouchDown];
102 [_voiceSearchButton
103 addTarget:delegate
104 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside)
105 forControlEvents:UIControlEventTouchUpInside];
77 106
78 for (NSString* title in buttonTitles) { 107 // Create separator
79 UIView* button = [self keyboardButtonWithTitle:title frame:currentFrame]; 108 UIView* separator = [[UIView alloc] init];
80 [parentView addSubview:button]; 109 [separator setTranslatesAutoresizingMaskIntoConstraints:NO];
81 currentFrame.origin.x = 110 [separator
82 CGRectGetMaxX(currentFrame) + betweenButtonSpacing; 111 setBackgroundColor:[UIColor colorWithWhite:0 alpha:kSeparatorAlpha]];
112 [separator.heightAnchor
113 constraintEqualToConstant:1.0 / [[UIScreen mainScreen] scale]]
114 .active = YES;
115 [self addSubview:separator];
116
117 // Position all the views.
118 NSDictionary* viewsDictionary = @{
119 @"cameraButton" : cameraButton,
120 @"voiceSearch" : _voiceSearchButton,
121 @"stackView" : stackView,
122 @"separator" : separator,
123 };
124 NSArray* constraints = @[
125 @"H:|-8-[cameraButton]-8-[voiceSearch]-(>=16)-[stackView]",
126 @"H:|-0-[separator]-0-|",
127 @"V:[separator]-0-|",
128 ];
129 ApplyVisualConstraintsWithOptions(constraints, viewsDictionary,
130 LayoutOptionForRTLSupport(), self);
131 AddSameCenterYConstraint(self, cameraButton);
132 AddSameCenterYConstraint(self, _voiceSearchButton);
133 AddSameCenterYConstraint(self, stackView);
134
135 NSLayoutConstraint* horizontallyCenterStackViewConstraint =
136 [self.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor];
137 horizontallyCenterStackViewConstraint.priority =
138 UILayoutPriorityDefaultHigh;
139 horizontallyCenterStackViewConstraint.active = YES;
140 } else {
141 const CGFloat kButtonInset = 5.0;
142 const CGFloat kButtonSizeX = 61.0;
143 const CGFloat kButtonSizeXCompact = 46.0;
144 const CGFloat kButtonSizeY = 62.0;
145 const CGFloat kButtonSizeYCompact = 35.0;
146 const CGFloat kBetweenButtonSpacing = 15.0;
147 const CGFloat kBetweenButtonSpacingCompact = 7.0;
148
149 // Center buttons in available space by placing them within a parent view
150 // that auto-centers.
151 CGFloat betweenButtonSpacing =
152 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing;
153 const CGFloat buttonWidth =
154 isCompact ? kButtonSizeXCompact : kButtonSizeX;
155
156 CGFloat totalWidth = (buttonTitles.count * buttonWidth) +
157 ((buttonTitles.count - 1) * betweenButtonSpacing);
158 CGFloat indent = floor((width - totalWidth) / 2.0);
159 if (indent < kButtonInset)
160 indent = kButtonInset;
161 CGRect parentViewRect = CGRectMake(indent, 0.0, totalWidth, height);
162 UIView* parentView = [[UIView alloc] initWithFrame:parentViewRect];
163 [parentView setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin |
164 UIViewAutoresizingFlexibleRightMargin];
165 [self addSubview:parentView];
166
167 // Create the shortcut buttons, starting at the left edge of |parentView|.
168 CGRect currentFrame =
169 CGRectMake(0.0, kButtonInset, buttonWidth,
170 isCompact ? kButtonSizeYCompact : kButtonSizeY);
171
172 for (NSString* title in buttonTitles) {
173 UIView* button =
174 [self keyboardButtonWithTitle:title frame:currentFrame];
175 [parentView addSubview:button];
176 currentFrame.origin.x =
177 CGRectGetMaxX(currentFrame) + betweenButtonSpacing;
178 }
179
180 // Create the voice search button and add it over the text buttons.
181 _voiceSearchButton = [UIButton buttonWithType:UIButtonTypeCustom];
182 [_voiceSearchButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
183 SetA11yLabelAndUiAutomationName(
184 _voiceSearchButton, IDS_IOS_ACCNAME_VOICE_SEARCH, @"Voice Search");
185 UIImage* voiceRow = [UIImage imageNamed:@"custom_row_voice"];
186 UIImage* voiceRowPressed =
187 [UIImage imageNamed:@"custom_row_voice_pressed"];
188 [_voiceSearchButton setBackgroundImage:voiceRow
189 forState:UIControlStateNormal];
190 [_voiceSearchButton setBackgroundImage:voiceRowPressed
191 forState:UIControlStateHighlighted];
192
193 UIImage* voiceIcon =
194 [UIImage imageNamed:@"voice_icon_keyboard_accessory"];
195 [_voiceSearchButton setAdjustsImageWhenHighlighted:NO];
196 [_voiceSearchButton setImage:voiceIcon forState:UIControlStateNormal];
197 [_voiceSearchButton setFrame:[self bounds]];
198 [_voiceSearchButton
199 addTarget:delegate
200 action:@selector(keyboardAccessoryVoiceSearchTouchDown)
201 forControlEvents:UIControlEventTouchDown];
202 [_voiceSearchButton
203 addTarget:delegate
204 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside)
205 forControlEvents:UIControlEventTouchUpInside];
206 [self addSubview:_voiceSearchButton];
83 } 207 }
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 } 208 }
112 209
113 return self; 210 return self;
114 } 211 }
115 212
116 - (void)setMode:(KeyboardAccessoryViewMode)mode { 213 - (void)setMode:(KeyboardAccessoryViewMode)mode {
214 if (experimental_flags::IsNewKeyboardAccessoryViewEnabled()) {
215 return;
216 }
117 _mode = mode; 217 _mode = mode;
118 switch (mode) { 218 switch (mode) {
119 case VOICE_SEARCH: 219 case VOICE_SEARCH:
120 [_voiceSearchButton setHidden:NO]; 220 [_voiceSearchButton setHidden:NO];
121 break; 221 break;
122 case KEY_SHORTCUTS: 222 case KEY_SHORTCUTS:
123 [_voiceSearchButton setHidden:YES]; 223 [_voiceSearchButton setHidden:YES];
124 break; 224 break;
125 } 225 }
126 } 226 }
(...skipping 18 matching lines...) Expand all
145 [button.titleLabel setFont:font]; 245 [button.titleLabel setFont:font];
146 [button setBackgroundImage:backgroundImage forState:UIControlStateNormal]; 246 [button setBackgroundImage:backgroundImage forState:UIControlStateNormal];
147 [button addTarget:self 247 [button addTarget:self
148 action:@selector(keyboardButtonPressed:) 248 action:@selector(keyboardButtonPressed:)
149 forControlEvents:UIControlEventTouchUpInside]; 249 forControlEvents:UIControlEventTouchUpInside];
150 button.isAccessibilityElement = YES; 250 button.isAccessibilityElement = YES;
151 [button setAccessibilityLabel:title]; 251 [button setAccessibilityLabel:title];
152 return button; 252 return button;
153 } 253 }
154 254
255 - (UIView*)newShortcutButtonWithTitle:(NSString*)title {
gambard 2017/06/09 12:35:42 Don't start method with new to avoid memory issue.
jif 2017/06/09 13:19:37 Good catch :-) Done and done.
256 const CGFloat kCornerRadius = 4.0;
257 const CGFloat kAlphaStateNormal = 0.1;
258 const CGFloat kAlphaStateHighlighted = 0.2;
259 const CGFloat kHorizontalEdgeInset = 8;
260 const CGFloat kIpadButtonTitleFontSize = 20.0;
261 const CGFloat kIphoneButtonTitleFontSize = 15.0;
262
263 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom];
264 UIFont* font = nil;
265
266 [button setTitle:title forState:UIControlStateNormal];
267 [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
268
269 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateNormal)
270 forState:UIControlStateNormal];
271 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateHighlighted)
272 forState:UIControlStateHighlighted];
273
274 button.layer.cornerRadius = kCornerRadius;
275 button.contentEdgeInsets =
276 UIEdgeInsetsMake(0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset);
277 button.clipsToBounds = YES;
278
279 if (IsIPadIdiom()) {
280 font = GetUIFont(FONT_HELVETICA, false, kIpadButtonTitleFontSize);
281 } else {
282 font = GetUIFont(FONT_HELVETICA, true, kIphoneButtonTitleFontSize);
283 }
284
285 [button.titleLabel setFont:font];
286
287 [button addTarget:self
288 action:@selector(keyboardButtonPressed:)
289 forControlEvents:UIControlEventTouchUpInside];
290 button.isAccessibilityElement = YES;
291 [button setAccessibilityLabel:title];
292 return button;
293 }
294
295 - (UIButton*)newIconButton:(NSString*)iconName {
296 const CGFloat kIconTintAlphaStateNormal = 0.45;
297 const CGFloat kIconTintAlphaStateHighlighted = 0.6;
298
299 UIColor* iconTintStateNormal = UIColorFromRGB(0, kIconTintAlphaStateNormal);
300 UIColor* iconTintStateHighlighted =
301 UIColorFromRGB(0, kIconTintAlphaStateHighlighted);
302
303 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom];
304
305 [button setTintColor:iconTintStateNormal forState:UIControlStateNormal];
306 [button setTintColor:iconTintStateHighlighted
307 forState:UIControlStateHighlighted];
308 [button setTranslatesAutoresizingMaskIntoConstraints:NO];
309 UIImage* icon = [[UIImage imageNamed:iconName]
310 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
311 [button setImage:icon forState:UIControlStateNormal];
312 return button;
313 }
314
155 - (BOOL)enableInputClicksWhenVisible { 315 - (BOOL)enableInputClicksWhenVisible {
156 return YES; 316 return YES;
157 } 317 }
158 318
159 - (void)keyboardButtonPressed:(id)sender { 319 - (void)keyboardButtonPressed:(id)sender {
160 UIButton* button = base::mac::ObjCCastStrict<UIButton>(sender); 320 UIButton* button = base::mac::ObjCCastStrict<UIButton>(sender);
161 [[UIDevice currentDevice] playInputClick]; 321 [[UIDevice currentDevice] playInputClick];
162 [_delegate keyPressed:[button currentTitle]]; 322 [_delegate keyPressed:[button currentTitle]];
163 } 323 }
164 324
165 @end 325 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698