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:
UIView
subclass.UITextField
to use the custom keyboard.Keyboard
class. This is a common source of error. You'll create this class in the next step. See the note at the end.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
@IBAction
method in the Swift or Objective-C owner to hook them all up.Add a UITextField
to your main storyboard and connect it to your view controller with an IBOutlet
. Call it textField
.
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
KeyboardDelegate
protocol that we defined above.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.
Make sure that the custom class for the root view is blank.
This example comes originally from this Stack Overflow answer.