mvm_core_ui/MVMCoreUI/BaseControllers/ScrollingViewController.swift
Pfeil, Scott Robert 335ec160b5 swift
2020-03-13 10:04:47 -04:00

110 lines
4.2 KiB
Swift

//
// 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)
}
}