I've made an in-app custom keyboard that replaces the system keyboard and pops up when I tap inside a UITextField.

Here is my code:
class ViewController: UIViewController {
    
    var myCustomKeyboard: UIView!
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let keyboardNib = UINib(nibName: "Keyboard", bundle: nil)
        myCustomKeyboard = keyboardNib.instantiateWithOwner(self, options: nil)[0] as! UIView
        
        textField.inputView = myCustomKeyboard
    }
}
The keyboard layout is loaded from an xib file.
How do I get the button text into the text field?
Notes:
Update
UIKeyInput protocol that UITextField conforms to, but how do I use it?I imagine something like this:
A new function to handle button event
func updateTextfield(sender: UIButton) {
    textField.text = (textField.text ?? "") + (sender.titleForState(.Normal) ?? "")
}
And after init your custom keyboard, register the buttons:
myCustomKeyboard.subviews
    .filter { $0 as? UIButton != nil } // Keep the buttons only
    .forEach { ($0 as! UIButton).addTarget(self, action: "updateTextfield", forControlEvents: .TouchUpInside)}
                        xib file that includes all your keysCreate a swift file with the same name as the xib file and set it as the file owner in the xib file setting.


Hook up all the key buttons to an IBAction method in the swift file. (See the code below.)
I'm using the delegate pattern to communicate between the custom keyboard view and the main view controller. This allows them to be decoupled. Multiple different custom keyboards could be swapped in and out without needing to change the detailed implementation code in the main view controller.
Keyboard.swift file
import UIKit
protocol KeyboardDelegate {
    func keyWasTapped(character: String)
}
class Keyboard: UIView {
    var delegate: KeyboardDelegate?
    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 needed
        let view = NSBundle.mainBundle().loadNibNamed(xibFileName, owner: self, options: nil)[0] as! UIView
        self.addSubview(view)
        view.frame = self.bounds
    }
    @IBAction func keyTapped(sender: UIButton) {
        self.delegate?.keyWasTapped(sender.titleLabel!.text!)
    }
}
Main view controller
Note that the ViewController conforms to the KeyboardDelegate protocol that we created. Also, when creating an instance of the keyboard view, the height needs to be set but the width doesn't. Apparently setting the inputView of the text field updates the keyboard view width to the screen width, which is convenient.
class ViewController: UIViewController, KeyboardDelegate {
    @IBOutlet weak var textField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        // get an instance of the Keyboard (only the height is important)
        let keyboardView = Keyboard(frame: CGRect(x: 0, y: 0, width: 0, height: 300))
        // use the delegate to communicate
        keyboardView.delegate = self
        // replace the system keyboard with the custom keyboard
        textField.inputView = keyboardView
    }
    // required method for keyboard delegate protocol
    func keyWasTapped(character: String) {
        textField.insertText(character)
    }
}
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