// // ScrollingViewController.swift // MVMCoreUI // // Created by Scott Pfeil on 3/12/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // import Foundation open class ScrollingViewController: ViewController { public var dismissKeyboardTapGesture: UITapGestureRecognizer? @IBOutlet public var scrollView: UIScrollView! public var contentView: UIView? public var contentWidthConstraint: NSLayoutConstraint? private var keyboardNotificationsAdded = false private var keyboardIsShowing = false private var preKeyboardContentInset: UIEdgeInsets? public init(with scrollView: UIScrollView) { self.scrollView = scrollView super.init(nibName: nil, bundle: nil) } required public init?(coder: NSCoder) { super.init(coder: coder) } public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) } // MARK: - View Life Cycle open override func viewDidLoad() { super.viewDidLoad() // Adds the tap gesture to dismiss the keyboard. dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput(sender:))) view.addGestureRecognizer(dismissKeyboardTapGesture!) dismissKeyboardTapGesture?.isEnabled = false scrollView.alwaysBounceVertical = false scrollView.delegate = self } open override func updateViewConstraints() { super.updateViewConstraints() // Sets the width of the content to the width of the screen. contentWidthConstraint?.constant = view.bounds.width - scrollView.contentInset.left - scrollView.contentInset.right } open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() view.setNeedsUpdateConstraints() view.layoutSubviews() } open override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) registerForKeyboardNotifications() } // MARK: - Keyboard Handling open func registerForKeyboardNotifications() { if !keyboardNotificationsAdded { keyboardNotificationsAdded = true NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil) } } open func unregisterForKeyboardNotifications() { if keyboardNotificationsAdded { NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) keyboardNotificationsAdded = false } } @objc open func keyboardWillShow(notification: Notification) { // Stores the current scroll insets if the keyboard was hidden. if !keyboardIsShowing { preKeyboardContentInset = scrollView.contentInset } keyboardIsShowing = true // Enables the tap gesture. dismissKeyboardTapGesture?.isEnabled = true MVMCoreUIUtility.setScrollViewInsetForKeyboardShow(notification, scrollView: scrollView, viewController: self) { [weak self] () -> CGRect in return self?.rectToScrollToWhenKeyboardPopsUp() ?? .zero } } @objc open func keyboardWillBeHidden(notification: Notification) { keyboardIsShowing = false // Disables the tap gesture. dismissKeyboardTapGesture?.isEnabled = false MVMCoreUIUtility.setScrollViewInsetForKeyboardHide(notification, scrollView: scrollView, viewController: self, contentInset: preKeyboardContentInset ?? scrollView.contentInset) } open func rectToScrollToWhenKeyboardPopsUp() -> CGRect? { guard let field = selectedField, let parent = selectedField?.superview else { return nil } return scrollView.convert(field.frame, from: parent) } }