Swift — Add a textField as inputAccessoryView

Payal Kandlur
3 min readJan 28, 2024

--

I recently encountered a situation that demanded a keyboard featuring an attached text field with a customized UI. This was necessary because the actual text field was obscured when the keyboard was visible, as illustrated below.

To address this, we simply need to incorporate an inputAccessoryView into the text field, which includes a view housing another text field.

To directly jump on to the full code check it here.

Now, let’s explore what we are set to implement.

Let’s straight jump into the implementation.

We encounter an issue where two text fields are obscured by the keyboard upon selection. To address this, we simply override the inputAccessoryView with a view that includes a text field.

override var inputAccessoryView: UIView {
return accessoryView
}

inputAccessoryView is typically used to define a custom accessory view that appears above the keyboard when a text input field becomes the first responder.

  • It is part of the UIResponder class and is commonly used in UIKit when working with text input fields (UITextField, UITextView).
  • It represents the custom view that is displayed above the system keyboard when a text input becomes the first responder.

accessoryView is another property or variable that holds a custom view intended to be used as an accessory view above the keyboard.

Now, let’s examine the user interface. Here’s how we generated the text field and placed it within a container view.

private lazy var accessoryTextField: UITextField = {
let textField = UITextField()
textField.borderStyle = .roundedRect
textField.backgroundColor = .clear
textField.returnKeyType = .done
textField.delegate = self
textField.autocorrectionType = .no
textField.spellCheckingType = .no
textField.translatesAutoresizingMaskIntoConstraints = false
textField.layer.borderColor = UIColor.black.cgColor
return textField
}()

func createAccessoryInputView(_ accessoryTextField: UITextField) -> UIView {
let containerView = UIView()
containerView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 70)
containerView.addSubview(accessoryTextField)
NSLayoutConstraint.activate([
accessoryTextField.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: constants.Offset16),
accessoryTextField.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -constants.Offset16),
accessoryTextField.topAnchor.constraint(equalTo: containerView.topAnchor, constant: constants.Offset8),
accessoryTextField.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -constants.Offset8),
])
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = .white
return containerView
}

This function createAccessoryInputView will be called in the viewDidLoad by adding the view to the accessoryView.

accessoryView = createAccessoryInputView(accessoryTextField)

Depending on the tags, we will dynamically assign appropriate texts to our accessoryViews when the keyboard is displayed. To achieve this, we will utilize observers to be notified of keyboard visibility changes.

The crucial point is to ensure that the accessoryTextField becomes the first responder when the main text field (firstNameTextField/lastNameTextField in our case) is tapped.

@objc func keyboardWillShow(notification: NSNotification) {
if let textfield = view.selectedTextField {
if textfield.tag == constants.tag1 {
accessoryTextField.text = firstNameTextField.text
accessoryTextField.placeholder = firstNameTextField.placeholder
accessoryTextField.tag = constants.tag3
} else if textfield.tag == constants.tag2 {
accessoryTextField.text = lastNameTextField.text
accessoryTextField.placeholder = lastNameTextField.placeholder
accessoryTextField.tag = constants.tag4
}
}
accessoryTextField.becomeFirstResponder()
}

Here handle the keyboardWillShow notification. selectedTextField keeps track of the presently selected text field.

Subsequently, the code evaluates the tag of the selected text field using conditional statements. If the tag corresponds to constants.tag1, the accessoryTextField is configured based on the properties of firstNameTextField. Alternatively, if the tag matches constants.tag2, the configuration is based on lastNameTextField. Tags, commonly employed to uniquely identify UI elements, facilitate the proper adjustment of the accessoryTextField.

Following the configuration steps, accessoryTextField.becomeFirstResponder() is invoked. This call designates accessoryTextField as the first responder, signifying it as the active input view. Consequently, the keyboard is displayed for this text field.

To get the selected text field in our view we have also added an extension to the UIView this way:

extension UIView {

// returns the textfields present in your current view
var textFieldsInView: [UITextField] {
return subviews
.filter({ !($0 is UITextField) })
.reduce(( subviews.compactMap { $0 as? UITextField }), { sum, current in
return sum + current.textFieldsInView
})
}

// returns the textfield currently in focus/selected/firstResponder
var selectedTextField: UITextField? {
return textFieldsInView.filter { $0.isFirstResponder }.first
}
}

That’s all!😊 Get the full code here. For any questions or suggestions, drop a comment!

--

--

No responses yet