Logo

How to set up a keyboard input accessory programmatically

I’ve been struggling with this for a while. I wanted to have a custom view above the iOS keyboard with just a label and two buttons. I tried to do this in a storyboard, but as it seems this isn’t an easy task. So I tried to do it in code. Turns out it’s pretty easy.

The set up

You will need a view controller with either a text field or a text view. Place it wherever you want. You will also need a property of the text field or text view in your view controller, so that you can assign the accessory view to your text field’s inputAccessoryView property.

Next comes the keyboard accessory.

Add a property of the accessory view and all views that belong to the accessory to your view controller file:

let accessory: UIView = {
    let accessoryView = UIView(frame: .zero)
    accessoryView.backgroundColor = .lightGray
    accessoryView.alpha = 0.6
    return accessoryView
}()
let cancelButton: UIButton = {
    let cancelButton = UIButton(type: .custom)
    cancelButton.setTitle("Cancel", for: .normal)
    cancelButton.setTitleColor(UIColor.red, for: .normal)
    cancelButton.addTarget(self, action:
    #selector(cancelButtonTapped), for: .touchUpInside)
    cancelButton.showsTouchWhenHighlighted = true
    return cancelButton
}()
let charactersLeftLabel: UILabel = {
    let charactersLeftLabel = UILabel()
    charactersLeftLabel.text = "256"
    charactersLeftLabel.textColor = UIColor.white
    return charactersLeftLabel
}()
let sendButton: UIButton! = {
    let sendButton = UIButton(type: .custom)
    sendButton.setTitleColor(.red, for: .normal)
    sendButton.setTitle("Send", for: .normal)
    sendButton.setTitleColor(.white, for: .disabled)
    sendButton.addTarget(self, action: #selector(sendButtonTapped), for: .touchUpInside)
    sendButton.showsTouchWhenHighlighted = true
    sendButton.isEnabled = true
    return sendButton
}()

Then in viewDidLoad() set up the accessory view (you can also add a function to add the accessory and call the function in viewDidLoad())

func addAccessory() {
    accessory.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 45)
    accessory.translatesAutoresizingMaskIntoConstraints = false
    cancelButton.translatesAutoresizingMaskIntoConstraints = false
    charactersLeftLabel.translatesAutoresizingMaskIntoConstraints = false
    sendButton.translatesAutoresizingMaskIntoConstraints = false
    textView.inputAccessoryView = accessory
    accessory.addSubview(cancelButton)
    accessory.addSubview(charactersLeftLabel)
    accessory.addSubview(sendButton)
    NSLayoutConstraint.activate([
    cancelButton.leadingAnchor.constraint(equalTo:
    accessory.leadingAnchor, constant: 20),
    cancelButton.centerYAnchor.constraint(equalTo:
    accessory.centerYAnchor),
    charactersLeftLabel.centerXAnchor.constraint(equalTo:
    accessory.centerXAnchor),
    charactersLeftLabel.centerYAnchor.constraint(equalTo:
    accessory.centerYAnchor),
    sendButton.trailingAnchor.constraint(equalTo:
    accessory.trailingAnchor, constant: -20),
    sendButton.centerYAnchor.constraint(equalTo:
    accessory.centerYAnchor)
    ])
}

That’s it. Now you’ve got a nice keyboard accessory view with two buttons and a label. The last thing to do is to add the action methods to the view controller, so that the buttons and the label do their stuff, but I leave this to you. ;-)

You can find the source code for this project here