I have created a form with 4 fields and one button. The view hierarchy looks like this: Main UIVIew, View (renamed contentView), on top of contentView I have 4 fields and 1 programmatically created button.
- When viewDidLoad is triggered, the button is not scrolled up so it can be visible in contentView.
- When starting to type in textFields, the textFields are scrolled up, outside of the viewable area.
- When firstResponder resigns (keyboard hidden) I cannot scroll the contentView. I will list the pictures screenshots in the order specified above.
Prior to this attempt, I pined the button on the ViewController's view, assigned the button's bottom constraint to a variable and when keyboardDidShow, I was adding the keyboard size to the bottom constraint, thus shooting the button up above the keyboard. However a stackoverflower said this method was prone to bugs: Move button when keyboard appears swift
I have followed this tutorial, but I don’t get same result. https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/
Given that Iphone has different screen sizes, please advise the best approach.
class EleventhViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var fullName: UITextField!
@IBOutlet weak var flatNumber: UITextField!
@IBOutlet weak var streetAddress: UITextField!
@IBOutlet weak var phoneNumber: UITextField!
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var scrollView: UIScrollView!
var nextButtonOutlet:UIButton!
override func viewDidLoad() {
super.viewDidLoad()
//called whenever keyboard is shown/hidden
registerForKeyboardNotifications()
//when identifies single or multiple taps, call DismissKeyboard
var tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "DismissKeyboard")
contentView.addGestureRecognizer(tap)
//create button programmatically
var button = UIButton(type: UIButtonType.custom) as UIButton
button = UIButton(frame: CGRect(x: 0, y: 637, width: 375, height: 50))
button.titleLabel?.textColor = UIColor.white
button.backgroundColor = UIColor(colorLiteralRed: 117/255, green: 232/255, blue: 0, alpha: 1)
button.setTitle("Next", for: .normal)
button.addTarget(self, action: #selector(EleventhViewController.nextButton), for: .touchUpInside)
self.contentView.addSubview(button)
self.nextButtonOutlet = button
//disable scroll bouncing
scrollView.bounces = false
self.fullName.delegate = self
self.flatNumber.delegate = self
self.streetAddress.delegate = self
self.phoneNumber.delegate = self
}
//Call this function when the tap is recognized.
func DismissKeyboard(){
contentView.endEditing(true)
}
// Stop Editing on Return Key Tap.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
weak var activeField: UITextField?
func keyboardDidShow(_ notification: Notification) {
//when a textfield is edited lift the button above the keyboard
if let activeField = self.activeField,let keyboardSize =
(notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as?
NSValue)?.cgRectValue {
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom:
keyboardSize.height, right: 0.0)
self.scrollView.contentInset = contentInsets
var aRect = self.view.frame
aRect.size.height -= keyboardSize.size.height
if !aRect.contains(nextButtonOutlet.frame.origin) {
self.scrollView.scrollRectToVisible(nextButtonOutlet.frame, animated: true)
}
}
func keyboardWillHide(_ notification: Notification) {
let contentInsets = UIEdgeInsets.zero
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
}
//Keep track of which textfield is being edited to make sure the field is visible when keyboard pops up
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeField = textField
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {
self.activeField = nil
}
//register for keyboard notifications
func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector:
#selector(keyboardDidShow),
name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector:
#selector(keyboardWillHide), name:
NSNotification.Name.UIKeyboardWillHide, object: nil)
}
//remove keyBoard observers
func deregisterFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name:
NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name:
NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(true)
//deregister keyboard notifications
deregisterFromKeyboardNotifications()
}
} //end of class
view Hierachy
When viewDidLoad is triggered,button does not show
When starting to type in textFields
When keyboard is hidden
Desired result