I have tried to create a custom keyboard in iOS 8 that replaces the stock one. I really searched and could not find out if it is possible to create a keyboard with more height than the stock iOS keyboard. I replaced UIInputView but could never manage to change the height available to me.
This is my code on Xcode 6.0 GM. Both orientations are supported.
Update: Thanks to @SoftDesigner, we can eliminate the constraint conflict
warning now.
Warning: XIB and storyboard are not tested. It's been reported by some folks that this does NOT work with XIB.
KeyboardViewController.h
#import <UIKit/UIKit.h> @interface KeyboardViewController : UIInputViewController @property (nonatomic) CGFloat portraitHeight; @property (nonatomic) CGFloat landscapeHeight; @property (nonatomic) BOOL isLandscape; @property (nonatomic) NSLayoutConstraint *heightConstraint; @property (nonatomic) UIButton *nextKeyboardButton; @end
KeyboardViewController.m
#import "KeyboardViewController.h" @interface KeyboardViewController () @end @implementation KeyboardViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Perform custom initialization work here self.portraitHeight = 256; self.landscapeHeight = 203; } return self; } - (void)updateViewConstraints { [super updateViewConstraints]; // Add custom view sizing constraints here if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0) return; [self.inputView removeConstraint:self.heightConstraint]; CGSize screenSize = [[UIScreen mainScreen] bounds].size; CGFloat screenH = screenSize.height; CGFloat screenW = screenSize.width; BOOL isLandscape = !(self.view.frame.size.width == (screenW*(screenW<screenH))+(screenH*(screenW>screenH))); NSLog(isLandscape ? @"Screen: Landscape" : @"Screen: Potriaint"); self.isLandscape = isLandscape; if (isLandscape) { self.heightConstraint.constant = self.landscapeHeight; [self.inputView addConstraint:self.heightConstraint]; } else { self.heightConstraint.constant = self.portraitHeight; [self.inputView addConstraint:self.heightConstraint]; } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; } - (void)viewDidLoad { [super viewDidLoad]; // Perform custom UI setup here self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.nextKeyboardButton setTitle:NSLocalizedString(@"Next Keyboard", @"Title for 'Next Keyboard' button") forState:UIControlStateNormal]; [self.nextKeyboardButton sizeToFit]; self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = NO; [self.nextKeyboardButton addTarget:self action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.nextKeyboardButton]; NSLayoutConstraint *nextKeyboardButtonLeftSideConstraint = [NSLayoutConstraint constraintWithItem:self.nextKeyboardButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]; NSLayoutConstraint *nextKeyboardButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.nextKeyboardButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; [self.view addConstraints:@[nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint]]; self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.inputView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0 constant:self.portraitHeight]; self.heightConstraint.priority = UILayoutPriorityRequired - 1; // This will eliminate the constraint conflict warning. } - (void)textWillChange:(id<UITextInput>)textInput { // The app is about to change the document's contents. Perform any preparation here. } - (void)textDidChange:(id<UITextInput>)textInput { } @end
Swift 1.0 version:
class KeyboardViewController: UIInputViewController { @IBOutlet var nextKeyboardButton: UIButton! let portraitHeight:CGFloat = 256.0 let landscapeHeight:CGFloat = 203.0 var heightConstraint: NSLayoutConstraint? override func updateViewConstraints() { super.updateViewConstraints() // Add custom view sizing constraints here if (self.view.frame.size.width == 0 || self.view.frame.size.height == 0) { return } inputView.removeConstraint(heightConstraint!) let screenSize = UIScreen.mainScreen().bounds.size let screenH = screenSize.height; let screenW = screenSize.width; let isLandscape = !(self.view.frame.size.width == screenW * ((screenW < screenH) ? 1 : 0) + screenH * ((screenW > screenH) ? 1 : 0)) NSLog(isLandscape ? "Screen: Landscape" : "Screen: Potriaint"); if (isLandscape) { heightConstraint!.constant = landscapeHeight; inputView.addConstraint(heightConstraint!) } else { heightConstraint!.constant = self.portraitHeight; inputView.addConstraint(heightConstraint!) } } override func viewDidLoad() { super.viewDidLoad() // Perform custom UI setup here self.nextKeyboardButton = UIButton.buttonWithType(.System) as UIButton self.nextKeyboardButton.setTitle(NSLocalizedString("Next Keyboard", comment: "Title for 'Next Keyboard' button"), forState: .Normal) self.nextKeyboardButton.sizeToFit() self.nextKeyboardButton.setTranslatesAutoresizingMaskIntoConstraints(false) self.nextKeyboardButton.addTarget(self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside) self.view.addSubview(self.nextKeyboardButton) var nextKeyboardButtonLeftSideConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0) var nextKeyboardButtonBottomConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0) self.view.addConstraints([nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint]) heightConstraint = NSLayoutConstraint(item: self.inputView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: portraitHeight) heightConstraint!.priority = 999.0 } override func textWillChange(textInput: UITextInput) { // The app is about to change the document's contents. Perform any preparation here. } override func textDidChange(textInput: UITextInput) { // The app has just changed the document's contents, the document context has been updated. var textColor: UIColor var proxy = self.textDocumentProxy as UITextDocumentProxy if proxy.keyboardAppearance == UIKeyboardAppearance.Dark { textColor = UIColor.whiteColor() } else { textColor = UIColor.blackColor() } self.nextKeyboardButton.setTitleColor(textColor, forState: .Normal) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With