Allow multiple scroll views inside a navigation controller

This commit is contained in:
Shadowfacts 2020-01-01 11:34:58 -05:00
parent f79d5a6b59
commit 85b437ab16
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
3 changed files with 41 additions and 11 deletions

View File

@ -56,6 +56,8 @@ public class SheetContainerViewController: UIViewController {
var contentScrollView: UIScrollView? { var contentScrollView: UIScrollView? {
delegate?.sheetContainerContentScrollView(self) ?? content.view as? UIScrollView delegate?.sheetContainerContentScrollView(self) ?? content.view as? UIScrollView
} }
var initialScrollViewContentOffset: CGPoint?
var scrollViewIsMovingSheet = false
public init(content: UIViewController) { public init(content: UIViewController) {
self.content = content self.content = content
@ -100,6 +102,10 @@ public class SheetContainerViewController: UIViewController {
panGesture.delegate = self panGesture.delegate = self
content.view.addGestureRecognizer(panGesture) content.view.addGestureRecognizer(panGesture)
contentScrollViewChanged()
}
public func contentScrollViewChanged() {
if let scrollView = contentScrollView { if let scrollView = contentScrollView {
scrollView.panGestureRecognizer.addTarget(self, action: #selector(scrollViewPanGestureRecognized)) scrollView.panGestureRecognizer.addTarget(self, action: #selector(scrollViewPanGestureRecognized))
} }
@ -134,14 +140,23 @@ public class SheetContainerViewController: UIViewController {
let shouldMoveSheetUp = topConstraint.constant > topDetent.offset && velocity.y < 0 // not fully expanded and dragging up let shouldMoveSheetUp = topConstraint.constant > topDetent.offset && velocity.y < 0 // not fully expanded and dragging up
let shouldMoveSheet = shouldMoveSheetDown || shouldMoveSheetUp let shouldMoveSheet = shouldMoveSheetDown || shouldMoveSheetUp
if shouldMoveSheet {
scrollView.bounces = false
scrollView.setContentOffset(CGPoint(x: 0, y: topContentOffset), animated: false)
}
switch recognizer.state { switch recognizer.state {
case .changed: case .began:
scrollView.bounces = false
scrollViewIsMovingSheet = shouldMoveSheet
if shouldMoveSheet { if shouldMoveSheet {
initialScrollViewContentOffset = scrollView.contentOffset
}
case .changed:
scrollViewIsMovingSheet = scrollViewIsMovingSheet || shouldMoveSheet
if scrollViewIsMovingSheet {
if initialScrollViewContentOffset == nil {
initialScrollViewContentOffset = scrollView.contentOffset
}
scrollView.setContentOffset(initialScrollViewContentOffset!, animated: false)
let translation = recognizer.translation(in: scrollView) let translation = recognizer.translation(in: scrollView)
setTopOffset(topConstraint.constant + translation.y) setTopOffset(topConstraint.constant + translation.y)
recognizer.setTranslation(.zero, in: scrollView) recognizer.setTranslation(.zero, in: scrollView)
@ -149,9 +164,12 @@ public class SheetContainerViewController: UIViewController {
case .ended: case .ended:
scrollView.bounces = true scrollView.bounces = true
if shouldMoveSheet { if scrollViewIsMovingSheet {
scrollView.setContentOffset(initialScrollViewContentOffset!, animated: false)
springToNearestDetent(verticalVelocity: velocity.y) springToNearestDetent(verticalVelocity: velocity.y)
} }
scrollViewIsMovingSheet = false
initialScrollViewContentOffset = nil
default: default:
break break
@ -165,8 +183,8 @@ public class SheetContainerViewController: UIViewController {
if offset < topOffset { if offset < topOffset {
let smoothed = smoothstep(value: offset, from: topOffset, to: 0) let smoothed = smoothstep(value: offset, from: topOffset, to: 0)
offset = topOffset - smoothed * maximumStretchDistance offset = topOffset - smoothed * maximumStretchDistance
} }
topConstraint.constant = offset topConstraint.constant = offset
dimmingView.alpha = lerp(offset, min: topOffset, max: bottomDetent.offset, from: maximumDimmingAlpha, to: minimumDimmingAlpha) dimmingView.alpha = lerp(offset, min: topOffset, max: bottomDetent.offset, from: maximumDimmingAlpha, to: minimumDimmingAlpha)
} }

View File

@ -44,6 +44,9 @@ class ContentTableViewController: UITableViewController {
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let navController = navigationController else { return } guard let navController = navigationController else { return }
navController.pushViewController(ContentTableViewController(), animated: true)
return
let vc = UIViewController() let vc = UIViewController()
vc.view.backgroundColor = .systemBackground vc.view.backgroundColor = .systemBackground
let label = UILabel() let label = UILabel()

View File

@ -10,6 +10,8 @@ import UIKit
import SheetImagePicker import SheetImagePicker
class ViewController: UIViewController { class ViewController: UIViewController {
var sheet: SheetContainerViewController!
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -37,7 +39,7 @@ class ViewController: UIViewController {
label.centerYAnchor.constraint(equalTo: blurView.contentView.centerYAnchor) label.centerYAnchor.constraint(equalTo: blurView.contentView.centerYAnchor)
]) ])
let sheet = SheetContainerViewController(content: content) sheet = SheetContainerViewController(content: content)
sheet.delegate = self sheet.delegate = self
sheet.detents = [.bottom, .middle, .top] sheet.detents = [.bottom, .middle, .top]
@ -50,7 +52,7 @@ class ViewController: UIViewController {
content.view.layer.masksToBounds = true content.view.layer.masksToBounds = true
content.view.layer.cornerRadius = view.bounds.width * 0.02 content.view.layer.cornerRadius = view.bounds.width * 0.02
let sheet = SheetContainerViewController(content: content) sheet = SheetContainerViewController(content: content)
sheet.delegate = self sheet.delegate = self
sheet.detents = [.bottom, .middle, .top] sheet.detents = [.bottom, .middle, .top]
@ -74,7 +76,7 @@ class ViewController: UIViewController {
nav.view.layer.masksToBounds = true nav.view.layer.masksToBounds = true
nav.view.layer.cornerRadius = view.bounds.width * 0.02 nav.view.layer.cornerRadius = view.bounds.width * 0.02
let sheet = SheetContainerViewController(content: nav) sheet = SheetContainerViewController(content: nav)
sheet.delegate = self sheet.delegate = self
sheet.detents = [.bottom, .middle, .top] sheet.detents = [.bottom, .middle, .top]
@ -85,11 +87,12 @@ class ViewController: UIViewController {
let table = ContentTableViewController() let table = ContentTableViewController()
let nav = UINavigationController(rootViewController: table) let nav = UINavigationController(rootViewController: table)
nav.delegate = self
nav.view.translatesAutoresizingMaskIntoConstraints = false nav.view.translatesAutoresizingMaskIntoConstraints = false
nav.view.layer.masksToBounds = true nav.view.layer.masksToBounds = true
nav.view.layer.cornerRadius = view.bounds.width * 0.02 nav.view.layer.cornerRadius = view.bounds.width * 0.02
let sheet = SheetContainerViewController(content: nav) sheet = SheetContainerViewController(content: nav)
sheet.delegate = self sheet.delegate = self
sheet.detents = [.bottom, .middle, .top] sheet.detents = [.bottom, .middle, .top]
@ -120,3 +123,9 @@ extension ViewController: SheetContainerViewControllerDelegate {
} }
} }
} }
extension ViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
sheet.contentScrollViewChanged()
}
}