Skip to content

Instantly share code, notes, and snippets.

@solos
Forked from agiletortoise/ViewController.swift
Created July 10, 2019 10:17
Show Gist options
  • Save solos/56d3791e8ed104446e0be0bdeafe6ee1 to your computer and use it in GitHub Desktop.
Save solos/56d3791e8ed104446e0be0bdeafe6ee1 to your computer and use it in GitHub Desktop.
How to update input accessory view to handle iPhone X with external keyboard
//
// ViewController.swift
// TEST_InputViewX
//
// Created by Greg Pierce on 10/5/17.
// Copyright © 2017 Agile Tortoise. All rights reserved.
//
// Demonstrates how to update an input accessory view
// to work on iPhone X with external keyboard attached
// using safe area insets.
//
// This adds the necessary padding under the input accessory
// So it's not clipped by home button area.
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
struct Constants {
static let AccessoryViewHeight: CGFloat = 44.0
}
@IBOutlet weak var textView: UITextView!
var accessoryView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
// observe keyboard events
let nc = NotificationCenter.default
nc.addObserver(self, selector: #selector(keyboardDidShow(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
nc.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
nc.addObserver(self, selector: #selector(keyboardWillChangeFrame(_:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
}
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
buildInputView()
textView.inputAccessoryView = accessoryView
return true
}
func buildInputView() {
// create input accessory view
guard accessoryView == nil else { return }
let accView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: self.view.bounds.size.width, height: Constants.AccessoryViewHeight))
accView.autoresizingMask = [.flexibleHeight] // important! allows it to resize
accView.backgroundColor = .red
// create a nested content view for your actual input controls
let contentView = UIView(frame: .zero)
contentView.backgroundColor = .green
// constrain content view to safe area of parent view
contentView.translatesAutoresizingMaskIntoConstraints = false
accView.addSubview(contentView)
contentView.leadingAnchor.constraint(equalTo: accView.safeAreaLayoutGuide.leadingAnchor).isActive = true
contentView.trailingAnchor.constraint(equalTo: accView.safeAreaLayoutGuide.trailingAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: accView.safeAreaLayoutGuide.topAnchor).isActive = true
contentView.heightAnchor.constraint(equalToConstant: Constants.AccessoryViewHeight).isActive = true
accessoryView = accView
}
func updateInputViewFrame() {
guard let accView = accessoryView else { return }
// calculate the accessory view height based on safe insets
let newHeight = accView.safeAreaInsets.bottom + Constants.AccessoryViewHeight
if newHeight != accView.frame.size.height {
accView.frame = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.size.width, height: newHeight)
textView.reloadInputViews()
}
}
@objc func keyboardDidShow(_ note: NSNotification) {
// update height of accessory view if needed
updateInputViewFrame()
}
@objc func keyboardWillChangeFrame(_ note: NSNotification) {
// update height of accessory view if needed
updateInputViewFrame()
}
@objc func keyboardWillHide(_ note: NSNotification) {
}
@IBAction func hideKeyboard(_ sender: Any) {
textView.resignFirstResponder()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment