iOS

Creating a Custom Keyboard Using iOS 8 App Extension


Prior to iOS 8, developers could provide custom keyboards or supplement the system keyboard with custom keys within only their application. With iOS 8, Apple has made it possible to create custom keyboards that will be able to be used system wide in other apps. You can now ship a custom keyboard with your app and users will be able to choose it as the keyboard to use for every app that requires text input.

To create a successful keyboard that users are more likely to keep on using, you have to meet some of the expectations that they have for what a keyboard should do. Since they will have been using the system keyboard for a long time, it is a good place to look at when deducing what your keyboard design and functionality should be.

custom-keyboard-featured

The system keyboard is fast, responsive and capable. It doesn’t interrupt the user with requests or information. Users have come to expect the following features from their keyboard. These are not requirements for creating custom keyboards, but just examples of what you could include in your keyboard to increase the chances of it being popular in a competitive market.

  • Auto suggestion and auto correction
  • Inserting period upon double space
  • Caps lock support
  • Keycap artwork
  • Multistage input for ideographic languages
  • Appropriate layout and features based on keyboard type trait for example presenting appropriate keys for easy email input when the user switches to an email field.

Custom Keyboard Limitations

There are some system keyboard features that are unavailable to custom keyboards. These include:

  • Custom keyboards don’t have access to most of the general keyboard settings in the Settings app such as Auto-capitalization, Enable Caps Lock or dictionary reset. However you can provide your own settings bundle that can be displayed in Settings.app. You can check the Implementing an iOS Settings Bundle guide for more on this.
  • A Custom Keyboard cannot be used to type into certain text input objects. These include the secure text input objects (any object that has its secureText property set to YES) and phone pad objects (any object that has a keyboard type trait of UIKeyboardTypePhonePad or UIKeyboardTypeNamePhonePad). When the user types in any of these text input objects, the system temporarily replaces your custom keyboard with the system keyboard, and on typing in a non-secure or non-phone pad object, your keyboard resumes.
  • Input dictation isn’t possible for a custom keyboard since, like all extensions in iOS 8, it has no access to the device microphone.
  • Selecting text is also not possible. Text selection is under the control of the app that is using the keyboard.
  • Closely related to the above point, editing menu options i.e. Cut, Copy, Paste are inaccessible. If an app provides an editing menu interface, the keyboard has no access to it.
  • You cannot display key artwork above the top edge of a custom keyboard’s primary view the same way Apple does when you tap and hold a key in the top view.
  • App developers can reject the use of custom keyboards in their app. This can especially be done in apps that are sensitive to security such as banking apps.

Essential Features of Custom Keyboards

The Apple Extensions guide specifies two development essentials for every custom keyboard:

  • Trust. A custom keyboard gives you access to what a user types. You should therefore establish and maintain their trust by being visible about privacy policies. Users should be assured that their keystroke data will only be used for the document they are typing and not for other purposes not obvious to them. If the keyboard employs use of other user data such as Location Service or Address Book database, then this should be conveyed to the user.
  • Next Keyboard key.This is a mandatory feature that allows users to switch to another keyboard. On the system keyboard, this is seen as the button with a globe on it. You tap once to switch to the next keyboard and long press it to view available keyboards.

Creating the Keyboard

We are going to look at two ways to build a keyboard’s UI – programmatically and using an Interface Builder document. The method you pick is a matter of preference, but I find that if the keyboard UI is complicated, it is better to use an Interface Builder document where you’ll be able to use Auto Layout and preview the effects of the constraints you’ve added without running the app, while in the case of creating the UI in code, you’ll end up writing a lot of code to set up constraints, which you can only see the effects of by running the project. Debugging this can be a bit of a headache.

To get started, create a new iPhone Simple View Application. Name it AC Custom Keyboard. This will be the container app for the custom keyboard. All extensions must be bundled within a containing app, and the containing app must provide some functionality. Apple are strict on this and so you cannot just have a skeleton container app whose sole purpose is to distribute your extension.

Next we’ll add an extension target to the project. Click on the project in the Project Navigator then select Editor > Add Target > iOS > Application Extension > Custom Keyboard and click Next

custom_extension

On the next window, set AC Keyboard as the product name and leave the other fields as they are and click Finish. You’ll be prompted to activate the new targets’ scheme, click Cancel.

A new group will have been created on the Project Navigator with the name of your keyboard – AC Keyboard. In it is the keyboard’s view controller and a property list file. The Info.plist file contains settings for the keyboard. Notable ones are:

  • Bundle display name – This is the display name for the keyboard, change it if you want a different name to be seen by users.
  • isASCIICapable – This is a key found within the NSExtension/NSExtensionAttributes dictionary. It determines if the custom keyboard can support ASCII characters.
  • PrefersRightToLeft – Specifies the direction of the primary language of the keyboard.
  • PrimaryLanguage – The primary language of the keyboard. The default is en-US.
  • RequestsOpenAccess – Determines the network access of the keyboard.

In Main.storyboard, add a TextView to the main View. Center it so that it completely covers the view. Run the application and bring up the keyboard by tapping anywhere on the screen. To change keyboards, tap the globe button on the system keyboard. If there is no globe button, tap the button with a smiley icon. If you want to see all available keyboards, hold the globe key and a list of keyboards will appear. Our keyboard isn’t on the list. You need to first add it in Settings.

Navigate to Settings > General > Keyboard > Keyboards > Add New Keyboard and select AC Custom Keyboard. This will add it to the list of available keyboards. Go back to your app and bring up the keyboard by tapping the text view. Tap and hold the globe key and select AC Keyboard from the list that pops up.

set-custom-keyboard

On switching from the system keyboard to the custom one, you will see an almost empty keyboard with only one button for the Next Keyboard.

keyboard_default_view

To add some keys to the keyboard, open KeyboardViewController.swift and make the following changes.

In viewDidLoad() add the following at the bottom of the function right after the code for the next keyboard button.

Next add the function below which will create buttons with titles of the strings passed into it.

This function iterates through an array of Strings and creates buttons with the respective titles. It also adds a target to each button so that when it is tapped, the function keyPressed() will be called. Next add this function.

Here you get the title of the tapped button and insert it at the insertion point of the current text input object via the textDocumentProperty. This is an object conforming to the UITextDocumentProxy protocol, which acts as a proxy between the keyboard and the text input object that summoned it.

Next we add the addConstraints() method which will add constraints to the buttons and the containingView.

Run the app and you should see a similar keyboard as shown below

programmatic_ui

As you can see, adding views programmatically requires you to set up constraints in code and if your keyboard’s UI is complicated and has many keys, this can get complicated and hard to debug. Next we will look at using the Interface Builder to create buttons.

Create a nib file by navigating to File > New > File > iOS > User Interface > View. Name it KeyboardView and make sure it is under the AC Keyboard target.

Select the nib’s view and in the Attributes Inspector, set its Size as Freeform and Status Bar to None. Then go to the Size Inspector and set its width to 320 and height to 220.

In KeyboardViewController.swift add the following in viewDidLoad() after the call to super.viewDidLoad(). This sets the nib file as the view of the view controller.

Add a view to the nib’s main view. Click on the Pin menu at the bottom of the Interface Builder interface and give it the following constraints – Height of 40, Trailing space of 0, Leading space of 0 and Top space to container of 42. Make sure Constrain to margin is not checked.

add_constraints

Add 9 buttons to the view. Set their text color to Dark Gray and change their titles to these letters respectively: ‘A’, ‘S’, ‘D’, ‘F’, ‘G’, ‘H’, ‘J’, ‘K’, ‘L’. Now for the constraints.

With each button, select the Align menu and select Vertical Center in Container.

alignment auto layout

Select the A button and add a Leading space to Superview fo 5. Select L and add a Leading space to Superview of 5. Control-drag from A to S and select Horizontal Spacing. We’ll change its value later. Do the same with S to D, D to F, F to G, and so on.

Select A and in the Size Inspector, make sure that its Leading Space to S ie set to a constant of 5. Select the next letter and set its Trailing space to the letter following it to 5. When you are done, all letters should have a Leading Space and Trailing space set to 5. Select the main view then Editor > Resolve Auto Layout Issues > All Views > Update Frames.

Run the application and you should see the keys you just added set up below the ones you added in code.

interface_builder_ui

To create outlets and actions for the keys, select the File’s Owner from the Document Outline, then in the Identity Inspector, set the class as KeyboardViewController. You can then create actions and outlets like you usually do in storyboard files by Control-dragging from a control to the view controller class. (You’ll see more of this in the example that follows).

Now that we have seen how to create a keyboard’s UI programmatically and with a nib file, let us add some functionality to it. For this, I have a starter project that we will be using. The project is a of a simple keyboard that we will add some functionality to. It is shown below. You should note that to keep it simple, I didn’t design for all size classes so, while it looks nice on the iPhone 5S, it doesn’t look quite the same for bigger screens. You can download the code here. Also note that the keyboard’s name is Appcoda Keyboard and not the AC Keyboard we had earlier.

keyboard_starter

I have already set up the actions and outlets we’ll require, but haven’t written the code for them (except for the Next Keyboard key).

First, you’ll notice that the Next Keyboard key has been replaced with a key titled KB. The action method for this can be seen it the view controller file as shown below.

We are first going to set up the actions for keys with letters and symbols i.e. any key you tap and see its title as the typed text. I created an action method for all these keys called keyPressed(). Modify this method as shown.

This is similar to what we had before. The title of the button is inserted at the insertion point of the current text input object via the textDocumentProperty. All the letters we type will be in Caps, but we will fix this shortly. Next modify the following functions to set up actions for the backspace(BS), space(SPACE) and return(RTN) keys respectively.

Run the app and test the keys.

In the view file, you will notice two views labelled Char Set 1 and Char Set 2. These are on the same row with one on top of the other. In viewDidLoad() the second view is hidden. Modify the charSetPressed() function as shown so that when the user presses the key labelled 1/2, the key’s text will change to 2/2 and a new set of characters will appear on the first row of the keyboard.

charset
If you look at the system keyboard, there is usually an indication, in the form of a brief animation when you tap a key. We should add some sort of feedback so the user knows that they tapped the right key. Add the following at the end of the keyPressed() method.

This makes a key scale up briefly when tapped before going back to its original size.

Lastly we’ll implement the Capslock key(CL). Modify the capsLockPressed() function as follows.

Notice that at the beginning of the file, we set capsLockOn to true. The above method toggles this value to be true/false and then calls a function that will change the case of the typed text as well as the title of the buttons. Add the following method to the class.

Run the app and you should be able to change the case of the letters.

custom keyboard - capslock

Conclusion

This tutorial doesn’t cover all that you can do with the keyboard extension. There is still a lot you can do to make the keyboard better. You can have it detect the beginning of sentences so that the first letter of the next typed word is capitalized, you can add auto-correction, auto-completion e.t.c. This is a new technology on the Apple platform, and it will be interesting to see what developers come up with.

For your reference, you can download the Xcode project here.

Tutorial
Building tvOS Movie Database App using The Movie Database (TMDb) API
iOS
A Beginner’s Guide to Automated UI Testing in iOS
iOS
How to Use SQLite to Manage Data in iOS Apps
  • Preston

    PrestonPreston

    Author Reply

    This is a great tutorial, but I was wondering how we can implement those special characters, like an Up arrow for Capitilize and. A globe for next keyboard. How do we access those?


    • Joyce Echessa

      Thanks. Capitalization and Next Keyboard key have been implemented. In the example, the Capitalize button is labelled CL (for caps lock) If you want an Up arrow for it, you will have to use an icon instead of text. The next keyboard key has also been implemented – it’s the button labelled KB. You can have the key display an icon instead of text (To do this, set the button’s Background to an image in the Attributes Inspector).
      If you want a globe icon specifically, you might run into some copyright issues with Apple, unless you design it to be very different from Apple’s. In the Apple HIG document, it is stated that you should avoid to use images that replicate Apple products and your icon design must not be easily mistaken for one of the system provided icons.
      Hope that helps.


  • Jezuz

    JezuzJezuz

    Author Reply

    Nice tutorial, as always!

    I would like to add the key sound to my custom keyboard but I cannot do that, and there is delay when I add the line:

    AudioServicesPlaySystemSound(1104)

    At the KeyPressend func.
    Is there any other way to add that sound?


  • Austin

    AustinAustin

    Author Reply

    For some reason I can’t get my iOS simulator to show this keyboard at all? I have made sure it’s activated in Settings.


    • fbara

      fbarafbara

      Author Reply

      I have the same problem and had to use my device instead of the simulators for this tutorial.


      • jai

        jaijai

        Author Reply

        Press command K when you have the mouse clicked on the keyboard.


    • Shashank

      ShashankShashank

      Author Reply

      I had the sam eproblem. I found that the custom keyboards don’t work in certain fields in the simulator. Try the search field and press command + K. That worked for me. Hope this helps someone else.


  • alex

    alexalex

    Author Reply

    Hi, i wana create armenian keyboard with its own character , can u help me?


  • Krishnayan Swami

    This is something I’ve been looking forward to try out too.
    I read Apple’s documentation but it was a little too overwhelming for me. This
    tutorial looks like a good start. Thank you.

    Outsource
    iPhone Application Development


  • fidele007

    fidele007fidele007

    Author Reply

    Hi, great tuturial. However, when I compiled the code and installed it on my iPhone, the keyboard won’t load at all. Is there something wrong?


  • Palash

    PalashPalash

    Author Reply

    Hi I’m not able to add UIImages for backspace and caps lock icons. How can I do that.

    Cheers,
    Palash


    • Joyce Echessa

      You can either set the image in Interface Builder or in code. In Interface builder, the button has an Image property that you can set in the Attributes Inspector.
      To set the image in code, use the following

      myButton.image = UIImage(named: “my_icon_image”)

      Hope that helps.


  • Hong Seongho

    hello I’m trying to make korean keyboard
    i made keyboard that have essential function
    but it has big problem
    example, I want to make “한글”
    but i make ㅎㅏㄴㄱㅡㄹ
    what should i do?


  • Syed

    SyedSyed

    Author Reply

    How do I add the long press gesture for the ‘delete’ key?


  • R.P Gayan Chanaka

    Hi Im totally a new to swift and programing

    when i compile i get a error with
    these two lines

    var buttons = createButtons(buttonTitles)

    addConstraints(buttons, containingView: topRow)

    it says

    use of unresolved identifier “createButtons”

    use of unresolved identifier “addConstraints”

    what i should do??

    please help

    Thank you


  • Rye

    RyeRye

    Author Reply

    Great tutorial. How would I adjust .xib to have it work on an iPhone 6 and 6 Super? Do I size the .xib for the 6 Super and then create autolayouts? Or something else?


  • Hammad Nasir

    Hello all, I’m having a problem here. I added the custom keyboard to the keyboards but it is not showing the custom keyboard in the available keyboards.
    What to do now?


  • Mike

    MikeMike

    Author Reply

    Hi Joyce, great tutorial, this has helped me get off the ground! I have been working with the NIB file, and when i try to instantiate it they way you do in your code, i get an error. It turns out that there isn’t anything being returned by the nib.InstantiateWithOwner call, so the array turns out to be empty. Any thoughts as to why this might be? I also tried to add your keyboardView.xib to my project – “This code is not key-value compliant for the key charset1”. any help you can give so i can get up and running would be great.


  • Neelanshu Goyal

    Hi Joyce, Great Tutorial ! I am working on a key board myself and i want to create long press linear popups like ios native keyboard for character kays. Could any one help me out.


    • Hana Belete

      hey , I am trying to do the long press action. have you managed to do it?


  • Guest

    GuestGuest

    Author Reply

    Hi, when I run the app even the regular keyboard won’t show up


  • Guest

    GuestGuest

    Author Reply

    So, one I just wanted to make sure I put this code in the right spot, and two; Xcode is not allowing me to run the app because of all of these errors. Someone please help me!!! P.S. Sorry I’m only a beginner


  • Theo Strauss

    Hi awesome tutorial but when i try to put in the code

    func createButtons(titles: [String]) -&gt [UIButton] {

    var buttons = [UIButton]()

    for title in titles {

    let button = UIButton.buttonWithType(.System) as UIButton

    button.setTitle(title, forState: .Normal)

    button.setTranslatesAutoresizingMaskIntoConstraints(false)

    button.backgroundColor = UIColor(white: 1.0, alpha: 1.0)

    button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)

    button.addTarget(self, action: “keyPressed:”, forControlEvents: .TouchUpInside)

    buttons.append(button)

    }

    return buttons

    }

    it says I need a semicolon before the “-&gt” and when I do that, it just gives me three more errors because it doesn’t know what “-&” or “gt” is. How do I fix this? Thanks a ton in advance


  • Isuru Nanayakkara

    Thanks for the tutorial. Very good introduction to keyboard extensions.


  • Chaleepa Mallawa

    Hi there. Thank you for this great tutorial. Is there a way to add long press to keys like this https://imgur.com/a/GQHve


  • Josh

    JoshJosh

    Author Reply

    Would love to have some feedback on my custom keyboard in the app store! There is a free & pro version, check it out here, called SmileyKey!

    https://itunes.apple.com/us/app/smileykey-pro-smiley-emoticon/id945226433?mt=8


  • Rahul Thakor

    Great Tutorial.
    Just to explore more I have changed my keyboard font to custom. but the problem is I’m not able to see output same as it should be.
    I’m using Raleway Light Google font.


  • Faizul Hasan

    when i compile i get a error with

    these two lines

    var buttons = createButtons(buttonTitles)

    addConstraints(buttons, containingView: topRow)

    it says

    use of unresolved identifier “createButtons”

    use of unresolved identifier “addConstraints”

    what i should do??


  • kiran

    kirankiran

    Author Reply

    How to add a clear button in this keyboard ?


  • erica simonson

    Hi, I don’t know a thing about code or development, but I have an awesome idea for a keyboard app for business, primarily for iOS. Any idea where to start? I’d just like to hire someone to build it.


  • vivek radadiya

    Thanks for this tutorial.

    Generally what we are doing is that first add some languages to keyboard by going to settings>general>keyboard settings>add new languages and then we can change keyboard languages from our app by using globe icon. This languages are only those which we have added into our keyboard manually.

    Now, I have created one app in swift. In this app there is 10 buttons denoting different languages. On button click, if the language is not added from settings then i want to programmatically add languages into keyboard without going to device’s settings app. Anyone having idea about this, Please?


Shares