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