I have a parent scroll view with a uiview header and table view. I am trying to have a similar behavior to Twitter or Instagram profile page. You start scrolling the parent scroll view and as soon as the header is gone there is a continuous transition from the scroll view scrolling to the table view scrolling without having to lift my finger and replace it on the table view. Right now the current behavior is a little jank. I have to lift my finger and put it on the table view after the scroll view content offset is past the header to start swiping the table view.
MainViewController
import UIKit
import XLPagerTabStrip
class MainViewController: UIViewController {
lazy var headerViewController: UIViewController = {
let header = UIViewController()
return header
}()
lazy var bottomViewControllers: BottomPageViewController = {
let bvc = BottomPageViewController()
return bvc
}()
lazy var scrollView: UIScrollView = {
let sv = UIScrollView()
sv.delegate = self
sv.showsVerticalScrollIndicator = false
sv.bounces = true
sv.bounces = false
return sv
}()
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(scrollView)
let f = UIScreen.main.bounds
scrollView.frame = CGRect(x: f.minX, y: f.minY, width: f.width, height: f.height)
add(headerViewController, to: scrollView, frame: CGRect(x: 0, y: 0, width: f.width, height: 150))
add(bottomViewControllers, to: scrollView, frame: CGRect(x: 0, y: headerViewController.view.bounds.height, width: f.width, height: f.height))
scrollView.contentSize = CGSize(width: f.width, height: f.height * 2)
if let vcs = bottomViewControllers.viewControllers as? [BottomViewController] {
for vc in vcs {
vc.delegate = self
}
}
}
}
extension MainViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let controllers = bottomViewControllers.viewControllers as? [BottomViewController] else { return }
let selectedController = controllers[bottomViewControllers.currentIndex]
if self.scrollView == scrollView {
selectedController.tableView.isScrollEnabled = self.scrollView.contentOffset.y >= 150
print(scrollView.contentOffset.y)
scrollView.isScrollEnabled = !selectedController.tableView.isScrollEnabled
bottomViewControllers.view.frame.origin.y = max(150, scrollView.contentOffset.y)
}
}
}
extension MainViewController: CustomScrollDelegate {
func tableViewScroll(_ viewController: BottomViewController) {
print(viewController.tableView.contentOffset.y)
viewController.tableView.isScrollEnabled = viewController.tableView.contentOffset.y > 0
}
}
BottomViewController
import UIKit
import XLPagerTabStrip
protocol CustomScrollDelegate {
func tableViewScroll(_ viewController: BottomViewController)
}
class BottomViewController: UITableViewController {
var pageTitle: String?
var pageIndex: Int = 0
var delegate: CustomScrollDelegate?
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .red
self.tableView.isUserInteractionEnabled = false
self.tableView.bounces = true
self.tableView.showsVerticalScrollIndicator = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "TETST")
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "TETST", for: indexPath) as? UITableViewCell else { return UITableViewCell() }
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
delegate?.tableViewScroll(self)
}
init(pageTitle: String, pageIndex: Int) {
self.pageTitle = pageTitle
self.pageIndex = pageIndex
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension BottomViewController: IndicatorInfoProvider {
func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
return IndicatorInfo.init(title: pageTitle ?? "Tab \(pageIndex)")
}
}