OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/chrome/browser/ui/toolbar/new_keyboard_accessory_view.h" |
| 6 |
| 7 #import <NotificationCenter/NotificationCenter.h> |
| 8 |
| 9 #include "base/mac/foundation_util.h" |
| 10 #include "ios/chrome/browser/experimental_flags.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" |
| 14 #include "ios/chrome/browser/ui/ui_util.h" |
| 15 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
| 16 #include "ios/chrome/grit/ios_strings.h" |
| 17 |
| 18 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 19 #error "This file requires ARC support." |
| 20 #endif |
| 21 |
| 22 @interface NewKeyboardAccessoryView () |
| 23 |
| 24 @property(nonatomic, weak) id<KeyboardAccessoryViewDelegate> delegate; |
| 25 |
| 26 // Called when a keyboard shortcut button is pressed. |
| 27 - (void)keyboardButtonPressed:(NSString*)title; |
| 28 // Creates a button shortcut for |title|. |
| 29 - (UIView*)shortcutButtonWithTitle:(NSString*)title; |
| 30 // Creates a button with an icon based on |iconName|. |
| 31 - (UIButton*)iconButton:(NSString*)iconName; |
| 32 |
| 33 @end |
| 34 |
| 35 @implementation NewKeyboardAccessoryView |
| 36 |
| 37 // Unused by this implementation of |KeyboardAccessoryViewProtocol|. |
| 38 @synthesize mode = _mode; |
| 39 |
| 40 @synthesize delegate = _delegate; |
| 41 |
| 42 - (instancetype)initWithButtons:(NSArray<NSString*>*)buttonTitles |
| 43 delegate:(id<KeyboardAccessoryViewDelegate>)delegate { |
| 44 const CGFloat kButtonMinSizeX = 61.0; |
| 45 const CGFloat kButtonMinSizeXCompact = 32.0; |
| 46 const CGFloat kButtonSizeY = 62.0; |
| 47 const CGFloat kButtonSizeYCompact = 30.0; |
| 48 const CGFloat kBetweenButtonSpacing = 15.0; |
| 49 const CGFloat kBetweenButtonSpacingCompact = 6.0; |
| 50 const CGFloat kSeparatorAlpha = 0.1; |
| 51 const CGFloat kViewHeight = 70.0; |
| 52 const CGFloat kViewHeightCompact = 43.0; |
| 53 const BOOL isCompact = IsCompact(); |
| 54 |
| 55 CGFloat width = [[UIScreen mainScreen] bounds].size.width; |
| 56 CGFloat height = isCompact ? kViewHeightCompact : kViewHeight; |
| 57 CGRect frame = CGRectMake(0.0, 0.0, width, height); |
| 58 |
| 59 self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard]; |
| 60 if (self) { |
| 61 _delegate = delegate; |
| 62 |
| 63 // Create and add stackview filled with the shortcut buttons. |
| 64 UIStackView* stackView = [[UIStackView alloc] init]; |
| 65 [stackView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 66 stackView.spacing = |
| 67 isCompact ? kBetweenButtonSpacingCompact : kBetweenButtonSpacing; |
| 68 for (NSString* title in buttonTitles) { |
| 69 UIView* button = [self shortcutButtonWithTitle:title]; |
| 70 [button setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 71 CGFloat buttonMinWidth = |
| 72 isCompact ? kButtonMinSizeXCompact : kButtonMinSizeX; |
| 73 [button.widthAnchor constraintGreaterThanOrEqualToConstant:buttonMinWidth] |
| 74 .active = YES; |
| 75 CGFloat buttonHeight = isCompact ? kButtonSizeYCompact : kButtonSizeY; |
| 76 [button.heightAnchor constraintEqualToConstant:buttonHeight].active = YES; |
| 77 [stackView addArrangedSubview:button]; |
| 78 } |
| 79 [self addSubview:stackView]; |
| 80 |
| 81 // Create and add buttons for voice and camera search. |
| 82 UIButton* cameraButton = [self iconButton:@"qr_scanner_keyboard_accessory"]; |
| 83 [cameraButton |
| 84 addTarget:_delegate |
| 85 action:@selector(keyboardAccessoryCameraSearchTouchUpInside) |
| 86 forControlEvents:UIControlEventTouchUpInside]; |
| 87 [self addSubview:cameraButton]; |
| 88 |
| 89 UIButton* voiceSearchButton = |
| 90 [self iconButton:@"voice_icon_keyboard_accessory"]; |
| 91 [self addSubview:voiceSearchButton]; |
| 92 [voiceSearchButton |
| 93 addTarget:_delegate |
| 94 action:@selector(keyboardAccessoryVoiceSearchTouchDown) |
| 95 forControlEvents:UIControlEventTouchDown]; |
| 96 [voiceSearchButton |
| 97 addTarget:_delegate |
| 98 action:@selector(keyboardAccessoryVoiceSearchTouchUpInside) |
| 99 forControlEvents:UIControlEventTouchUpInside]; |
| 100 |
| 101 // Create and add 1 pixel high separator view. |
| 102 UIView* separator = [[UIView alloc] init]; |
| 103 [separator setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 104 [separator |
| 105 setBackgroundColor:[UIColor colorWithWhite:0 alpha:kSeparatorAlpha]]; |
| 106 [separator.heightAnchor |
| 107 constraintEqualToConstant:1.0 / [[UIScreen mainScreen] scale]] |
| 108 .active = YES; |
| 109 [self addSubview:separator]; |
| 110 |
| 111 // Position all the views. |
| 112 NSDictionary* viewsDictionary = @{ |
| 113 @"cameraButton" : cameraButton, |
| 114 @"voiceSearch" : voiceSearchButton, |
| 115 @"stackView" : stackView, |
| 116 @"separator" : separator, |
| 117 }; |
| 118 NSArray* constraints = @[ |
| 119 @"H:|-8-[cameraButton]-8-[voiceSearch]-(>=16)-[stackView]", |
| 120 @"H:|-0-[separator]-0-|", |
| 121 @"V:[separator]-0-|", |
| 122 ]; |
| 123 ApplyVisualConstraintsWithOptions(constraints, viewsDictionary, |
| 124 LayoutOptionForRTLSupport(), self); |
| 125 AddSameCenterYConstraint(self, cameraButton); |
| 126 AddSameCenterYConstraint(self, voiceSearchButton); |
| 127 AddSameCenterYConstraint(self, stackView); |
| 128 // The following constraint is supposed to break if there's not enough |
| 129 // space to center the stack view. |
| 130 NSLayoutConstraint* horizontallyCenterStackViewConstraint = |
| 131 [self.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor]; |
| 132 horizontallyCenterStackViewConstraint.priority = |
| 133 UILayoutPriorityDefaultHigh; |
| 134 horizontallyCenterStackViewConstraint.active = YES; |
| 135 } |
| 136 return self; |
| 137 } |
| 138 |
| 139 - (UIView*)shortcutButtonWithTitle:(NSString*)title { |
| 140 const CGFloat kCornerRadius = 4.0; |
| 141 const CGFloat kAlphaStateNormal = 0.1; |
| 142 const CGFloat kAlphaStateHighlighted = 0.2; |
| 143 const CGFloat kHorizontalEdgeInset = 8; |
| 144 const CGFloat kIpadButtonTitleFontSize = 20.0; |
| 145 const CGFloat kIphoneButtonTitleFontSize = 15.0; |
| 146 |
| 147 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom]; |
| 148 UIFont* font = nil; |
| 149 |
| 150 [button setTitle:title forState:UIControlStateNormal]; |
| 151 [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; |
| 152 |
| 153 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateNormal) |
| 154 forState:UIControlStateNormal]; |
| 155 [button setBackgroundColor:UIColorFromRGB(0, kAlphaStateHighlighted) |
| 156 forState:UIControlStateHighlighted]; |
| 157 |
| 158 button.layer.cornerRadius = kCornerRadius; |
| 159 button.contentEdgeInsets = |
| 160 UIEdgeInsetsMake(0, kHorizontalEdgeInset, 0, kHorizontalEdgeInset); |
| 161 button.clipsToBounds = YES; |
| 162 |
| 163 if (IsIPadIdiom()) { |
| 164 font = [UIFont systemFontOfSize:kIpadButtonTitleFontSize]; |
| 165 } else { |
| 166 font = [UIFont boldSystemFontOfSize:kIphoneButtonTitleFontSize]; |
| 167 } |
| 168 |
| 169 [button.titleLabel setFont:font]; |
| 170 |
| 171 [button addTarget:self |
| 172 action:@selector(keyboardButtonPressed:) |
| 173 forControlEvents:UIControlEventTouchUpInside]; |
| 174 button.isAccessibilityElement = YES; |
| 175 [button setAccessibilityLabel:title]; |
| 176 return button; |
| 177 } |
| 178 |
| 179 - (UIButton*)iconButton:(NSString*)iconName { |
| 180 const CGFloat kIconTintAlphaStateNormal = 0.45; |
| 181 const CGFloat kIconTintAlphaStateHighlighted = 0.6; |
| 182 |
| 183 UIColor* iconTintStateNormal = UIColorFromRGB(0, kIconTintAlphaStateNormal); |
| 184 UIColor* iconTintStateHighlighted = |
| 185 UIColorFromRGB(0, kIconTintAlphaStateHighlighted); |
| 186 |
| 187 ColoredButton* button = [ColoredButton buttonWithType:UIButtonTypeCustom]; |
| 188 |
| 189 [button setTintColor:iconTintStateNormal forState:UIControlStateNormal]; |
| 190 [button setTintColor:iconTintStateHighlighted |
| 191 forState:UIControlStateHighlighted]; |
| 192 [button setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 193 UIImage* icon = [[UIImage imageNamed:iconName] |
| 194 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
| 195 [button setImage:icon forState:UIControlStateNormal]; |
| 196 return button; |
| 197 } |
| 198 |
| 199 - (BOOL)enableInputClicksWhenVisible { |
| 200 return YES; |
| 201 } |
| 202 |
| 203 - (void)keyboardButtonPressed:(id)sender { |
| 204 UIButton* button = base::mac::ObjCCastStrict<UIButton>(sender); |
| 205 [[UIDevice currentDevice] playInputClick]; |
| 206 [_delegate keyPressed:[button currentTitle]]; |
| 207 } |
| 208 |
| 209 @end |
OLD | NEW |