0

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
}

}
Rahul Kumar
  • 3,009
  • 2
  • 16
  • 22
  • Have you checked this answer ? [Move view with keyboard using Swift](https://stackoverflow.com/questions/26070242/move-view-with-keyboard-using-swift) – Nathan Barreto Sep 29 '17 at 13:07

1 Answers1

0

If you are creating a Form for users where they can enter information then I would suggest using a static UITableView. Static UITableView can be used if your UIViewController is of type UITableViewController. Static TableView makes it very easy to place controls and since UITableView already has a UIScrollView it automatically scrolls when the UITextView is in focus.

Try it out: enter image description here

azamsharp
  • 19,710
  • 36
  • 144
  • 222