Create a custom in-app keyboard
suggest change![](/essential/ios/img/c0de08515fcad9eec65cfed738780f25d2cc37e7.gif)
This is a basic in-app keyboard. The same method could be used to make just about any keyboard layout. Here are the main things that need to be done:
- Create the keyboard layout in an .xib file, whose owner is a Swift or Objective-C class that is a
UIView
subclass. - Tell the
UITextField
to use the custom keyboard. - Use a delegate to communicate between the keyboard and the main view controller.
Create the .xib keyboard layout file
- In Xcode go to File > New > File… > iOS > User Interface > View to create the .xib file.
- I called mine Keyboard.xib
- Add the buttons that you need.
- Use auto layout constraints so that no matter what size the keyboard is, the buttons will resize accordingly.
- Set the File’s Owner (not the root view) to be the
Keyboard
class. This is a common source of error. You’ll create this class in the next step. See the note at the end.
Create the .swift UIView subclass keyboard file
- In Xcode go to File > New > File… > iOS > Source > Cocoa Touch Class to create the Swift or Objective-C class. Choose
UIView
as a superclass for newly created class - I called mine
Keyboard.swift
(Keyboard
class in Objective-C) - Add the following code for Swift:
import UIKit
// The view controller will adopt this protocol (delegate)
// and thus must contain the keyWasTapped method
protocol KeyboardDelegate: class {
func keyWasTapped(character: String)
}
class Keyboard: UIView {
// This variable will be set as the view controller so that
// the keyboard can send messages to the view controller.
weak var delegate: KeyboardDelegate?
// MARK:- keyboard initialization
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initializeSubviews()
}
override init(frame: CGRect) {
super.init(frame: frame)
initializeSubviews()
}
func initializeSubviews() {
let xibFileName = "Keyboard" // xib extention not included
let view = NSBundle.mainBundle().loadNibNamed(xibFileName, owner: self, options: nil)[0] as! UIView
self.addSubview(view)
view.frame = self.bounds
}
// MARK:- Button actions from .xib file
@IBAction func keyTapped(sender: UIButton) {
// When a button is tapped, send that information to the
// delegate (ie, the view controller)
self.delegate?.keyWasTapped(sender.titleLabel!.text!) // could alternatively send a tag value
}
}
- Add the following code for Objective-C:
**Keyboard.h File**
#import <UIKit/UIKit.h>
// The view controller will adopt this protocol (delegate)
// and thus must contain the keyWasTapped method
@protocol KeyboardDelegate<NSObject>
- (void)keyWasTapped:(NSString *)character;
@end
@interface Keyboard : UIView
@property (nonatomic, weak) id<KeyboardDelegate> delegate;
@end
Keyboard.m File
#import "Keyboard.h"
@implementation Keyboard
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
[self initializeSubviews];
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
[self initializeSubviews];
return self;
}
- (void)initializeSubviews {
NSString *xibFileName = @"Keyboard"; // xib extention not included
UIView *view = [[[NSBundle mainBundle] loadNibNamed:xibFileName owner:self options:nil] firstObject];
[self addSubview:view];
view.frame = self.bounds;
}
// MARK:- Button actions from .xib file
-(IBAction)keyTapped:(UIButton *)sender {
// When a button is tapped, send that information to the
// delegate (ie, the view controller)
[self.delegate keyWasTapped:sender.titleLabel.text]; // could alternatively send a tag value
}
@end
- Control drag actions from the buttons to button callback in the .xib file to the
@IBAction
method in the Swift or Objective-C owner to hook them all up. - Note that the protocol and delegate code. See this answer for a simple explanation about how delegates work.
Set up the View Controller
- Add a
UITextField
to your main storyboard and connect it to your view controller with anIBOutlet
. Call ittextField
. - Use the following code for the View Controller in Swift:
import UIKit
class ViewController: UIViewController, KeyboardDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// initialize custom keyboard
let keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 300))
keyboardView.delegate = self // the view controller will be notified by the keyboard whenever a key is tapped
// replace system keyboard with custom keyboard
textField.inputView = keyboardView
}
// required method for keyboard delegate protocol
func keyWasTapped(character: String) {
textField.insertText(character)
}
}
- Use the following code for Objective-C:
.h File
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
.m File
#import "ViewController.h"
#import "Keyboard.h"
@interface ViewController ()<KeyboardDelegate>
@property (nonatomic, weak) IBOutlet UITextField *textField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// initialize custom keyboard
Keyboard *keyboardView = [[Keyboard alloc] initWithFrame:CGRectMake(0, 0, 0, 300)];
keyboardView.delegate = self; // the view controller will be notified by the keyboard whenever a key is tapped
// replace system keyboard with custom keyboard
self.textField.inputView = keyboardView;
}
- (void)keyWasTapped:(NSString *)character {
[self.textField insertText:character];
}
@end
- Note that the view controller adopts the
KeyboardDelegate
protocol that we defined above.
Common error
If you are getting an EXC_BAD_ACCESS
error, it is probably because you set the view’s custom class as Keyboard
rather than do this for the nib File’s Owner.
Select Keyboard.nib
and then choose File’s Owner.
![](/essential/ios/img/75aadceb36368e538e51235532963e233d14beef.png)
Make sure that the custom class for the root view is blank.
![](/essential/ios/img/dfbb96e82c7b804b6d5dccd8175c9b163b14ee96.png)
Notes
This example comes originally from this Stack Overflow answer.
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents