mvm_core_ui/MVMCoreUI/BaseControllers/ScrollingViewController.swift

135 lines
5.0 KiB
Swift

//
// ScrollingViewController.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 3/12/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
open class ScrollingViewController: ViewController {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var dismissKeyboardTapGesture: UITapGestureRecognizer?
@IBOutlet public var scrollView: UIScrollView!
public var contentView: UIView?
private var keyboardNotificationsAdded = false
private var keyboardIsShowing = false
private var preKeyboardContentInset: UIEdgeInsets?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
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 Lifecycle
//--------------------------------------------------
open override func viewDidLoad() {
super.viewDidLoad()
// Adds the tap gesture to dismiss the keyboard.
dismissKeyboardTapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissFieldInput))
view.addGestureRecognizer(dismissKeyboardTapGesture!)
dismissKeyboardTapGesture?.isEnabled = false
scrollView.alwaysBounceVertical = false
scrollView.delegate = self
}
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
view.setNeedsUpdateConstraints()
view.layoutSubviews()
}
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerForKeyboardNotifications()
}
open override func updateUI() {
super.updateUI()
// will change scrollView indicatorStyle automatically on the basis of backgroundColor
var greyScale: CGFloat = 0
if view.backgroundColor?.getWhite(&greyScale, alpha: nil) ?? false {
scrollView.indicatorStyle = greyScale > 0.5 ? .black : .white
}
scrollView.flashScrollIndicators()
}
open func scrollViewDidScroll(_ scrollView: UIScrollView) {
executeBehaviors { [weak self] (behavior: PageScrolledBehavior) in
behavior.pageScrolled(scrollView: scrollView, self?.delegateObjectIVar)
}
}
//--------------------------------------------------
// 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)
}
}