I'm creating a form that lives on a view within a scrollview. It contains two textFields and one textView. I've cobbled together some code from online resources(like this one) so that it scrolls up if a textField is ever too low on the view/obstructed by the keyboard. The problem is that it doesn't seem to work for textViews.
I've done my best to comprehend why textViews won't trigger the same behavior, but I could really use some help. Here's my VC code:
import UIKit
class AddAPlaceBasicInfoViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
// Outlets
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var categoryTextField: UITextField!
@IBOutlet weak var descriptionTextView: UITextView!
@IBOutlet weak var nextButton: UIButton!
@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(noti:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(noti:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
// Default to an disabled "Next" button.
nextButton.isEnabled = false
nextButton.backgroundColor = UIColor(red: 89/255, green: 89/255, blue: 89/255, alpha: 1/1)
// Check that fields are filled.
nameTextField.delegate = self
descriptionTextView.delegate = self
// Helper functions.
createToolbar()
descriptionTextViewSetup(descriptionTextView)
}
// Creates the done button above the category picker.
func createToolbar() {
// Creates an instance of UIToolbar() named "toolbar".
let toolbar = UIToolbar()
toolbar.sizeToFit()
// Set up button properties.
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(AddAPlaceBasicInfoViewController.dismissKeyboard))
// Set color to teal.
doneButton.tintColor = UIColor(red: 0/255, green: 134/255, blue: 111/255, alpha: 1)
// Set up button in the toolbar and make it interactive.
toolbar.setItems([doneButton], animated: false)
toolbar.isUserInteractionEnabled = true
// Add the toolbar as an accessory view to the category picker.
nameTextField.inputAccessoryView = toolbar
categoryTextField.inputAccessoryView = toolbar
descriptionTextView.inputAccessoryView = toolbar
// Set toolbar's background to white.
toolbar.backgroundColor = UIColor.white
}
// Function to dismiss the keyboard. Used when the user taps the "Done" button in the toolbar.
func dismissKeyboard() {
view.endEditing(true)
if nameTextField.text?.characters.count == 0 || categoryTextField.text?.characters.count == 0 || descriptionTextView.text == "What's this place like? (You'll be able to add a photo on the next screen)" {
nextButton.isEnabled = false
nextButton.backgroundColor = UIColor(red: 89/255, green: 89/255, blue: 89/255, alpha: 1/1)
} else {
nextButton.isEnabled = true
nextButton.backgroundColor = UIColor(red: 0/255, green: 134/255, blue: 111/255, alpha: 1/1)
}
}
// Function to create placeholder text.
func descriptionTextViewSetup(_ textView: UITextView) {
// Modifications
descriptionTextView.text = "What's this place like? (You'll be able to add a photo on the next screen)"
descriptionTextView.textColor = UIColor(red: 199/255, green: 199/255, blue: 205/255, alpha: 1/1)
descriptionTextView.textContainer.lineFragmentPadding = 0
//descriptionTextView.textColor = UIColor.lightGray
}
//---------------------------------
// MARK: - Notification Center
//---------------------------------
func keyboardWillHide(noti: Notification) {
let contentInsets = UIEdgeInsets.zero
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
func keyboardWillShow(noti: Notification) {
guard let userInfo = noti.userInfo else { return }
guard var keyboardFrame: CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return }
keyboardFrame = self.view.convert(keyboardFrame, from: nil)
var contentInset:UIEdgeInsets = scrollView.contentInset
contentInset.bottom = keyboardFrame.size.height
scrollView.contentInset = contentInset
}
}