iOS Custom Keyboard

iOS provides a default onscreen keyboard. What if it does not fit your app's requirements? There is a simple way to extend it to include your own custom keyboards.

 

In my recent Caption Me app for iPhone and iPad, I need to extend the default system keyboard by adding several custom keyboards, such as font chooser and colour picker keyboards.

Caption Me Caption Me

 

Custom Keyboard just another UIView

As it turns out it was easier to achieve than first thought. Each custom keyboard is in fact just a UIView. For example, the interface of my FontChooserView is something like

@interface FontChooserView : UIView

 

@property(weak, nonatomic) NSObject<FontChooserViewDelegate>* delegate;

- (void)setFont:(UIFont*)font;

- (UIFont*)getFont;

@end

 

In the implementation, I did the usual stuff like creating all the required UI controls, including UITableView for choosing the font and UISlider for changing the font size.

 

The only trick is to tell the iOS system that it should launch the font chooser instead of showing the system keyboard. This can be done by changing the inputView of the UITextField or UITextView to point towards my custom keyboard view, e.g. my FontChooserView.

self.textView.inputView = self.fontChooserView;

 

The only downside of this approach is that it will always show the font chooser and there is no way to return to the system keyboard.

 

 

Input Accessory View

Fortunately, iOS supports input accessory, which is another UIView placed just above the keyboard. You can treat it as a toolbar and put your own buttons there, e.g. one button for showing the system keyboard, one for font chooser, one for colour picker, etc.

 

So how can we implement it? This is the responsibility of the controller that holds the UITextField and the UITextView instances. You need to provide and implement the following method and return your toobar view.

 

An example of input accessory view that contains two buttons.

- (UIView*)inputAccessoryView

{

if (!_inputAccessoryView)

{

// lazy creation

CGRect accessFrame = CGRectMake(0, 0, 1024, 50);

_inputAccessoryView = [[UIView alloc] initWithFrame:accessFrame];

 

// create a semi-transparent banner

UIView* iavBackgroundView = [[UIView alloc] initWithFrame:accessFrame];

iavBackgroundView.backgroundColor = [UIColor darkGrayColor];

iavBackgroundView.alpha = 0.5;

[_inputAccessoryView addSubview:iavBackgroundView];

 

// create a button for system keyboard

UIImage* image = [UIImage imageNamed:@"btn-keyboard"];

UIButton* kbButton = [UIButton buttonWithType:UIButtonTypeCustom];

kbButton.frame = CGRectMake(10, 5, 40, 40);

[kbButton setImage:image forState:UIControlStateNormal];

[kbButton addTarget:self

action:@selector(kbButtonPressed:)

forControlEvents:UIControlEventTouchUpInside];

[_inputAccessoryView addSubview:kbButton];

 

// create a button for our font & size keyboard

image = [UIImage imageNamed:@"btn-font"];

UIButton* fontButton = [UIButton buttonWithType:UIButtonTypeCustom];

fontButton.frame = CGRectMake(60, 5, 40, 40);

[fontButton setImage:image forState:UIControlStateNormal];

[fontButton addTarget:self

action:@selector(fontButtonPressed:)

forControlEvents:UIControlEventTouchUpInside];

[_inputAccessoryView addSubview:fontButton];

}

return _inputAccessoryView;

}

 

As the result of this code, a semi-transparent toolbar with two buttons is placed just above the keyboard.

Input Accessory

 

Switching between Keyboards

When one of these two buttons is pressed, you need to dynamically switch to the appropriate keyboard.

 

For example, switching to the font chooser by pointing the inputView of the UITextField or the UITextView to the fontChooserView instance.

- (void)fontButtonPressed:(id)sender

{

// change to our font & size keyboard

self.textView.inputView = self.fontChooserView;

[self.textView reloadInputViews];

}

 

This will show the font chooser keyboard.

Font Chooser Keyboard

 

Switching to the system keyboard by resetting the inputView of the UITextField or the UITextView object.

- (void)kbButtonPressed:(id)sender

{

// change to the system keyboard

self.textView.inputView = nil;

[self.textView reloadInputViews];

}

 

Note: remember to reload the input view by calling the reloadInputViews method on the UITextField or the UITextView object.

 

 

If you are interested, you can download my sample project (CustomKeyboard.zip), which is a complete Xcode 4.6 project.