Swift 一定以上スクロールしたらタブの位置を固定する(SwipeMenuViewControllerを使う)
やりたいことはこちらのページに書かれていたようなこと
https://techblog.zozo.com/entry/scroll_tab_page
https://github.com/yysskk/SwipeMenuViewController
SwipeMenuViewControllerというライブラリを使って試してみた
ViewController.swift
import UIKit import SwipeMenuViewController class ViewController: UIViewController, SwipeMenuViewDelegate, SwipeMenuViewDataSource, UIScrollViewDelegate, TableViewControllerProtocol { var menus = ["メニュー1", "メニュー2", "メニュー3"] var header: UIView! var scrollView = UIScrollView() var swipeMenuView: SwipeMenuView! override func viewDidLoad() { super.viewDidLoad() // タブの上のView header = UIView(frame: CGRect(x: 10, y: 20, width: view.frame.width - 10*2, height: 200)) header.backgroundColor = UIColor.init(red: 157/255, green: 204/255, blue: 224/255, alpha: 1) scrollView.delegate = self scrollView.addSubview(header) // SwipeMenuView swipeMenuView = SwipeMenuView(frame: CGRect(x: 0, y: header.frame.origin.y + header.frame.height, width: view.frame.width, height: view.frame.height)) swipeMenuView.delegate = self swipeMenuView.dataSource = self scrollView.addSubview(swipeMenuView) var options: SwipeMenuViewOptions = .init() options.tabView.style = .segmented self.swipeMenuView.reloadData(options: options, default: nil, isOrientationChange: false) scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height) scrollView.contentSize = CGSize(width: view.frame.width, height: view.frame.height + 100) view.addSubview(scrollView) } // タブの数を返します func numberOfPages(in swipeMenuView: SwipeMenuView) -> Int { return menus.count } // タブのテキストを返します func swipeMenuView(_ swipeMenuView: SwipeMenuView, titleForPageAt index: Int) -> String { return menus[index] } // タブが選択されたときに表示するViewControllerを返します func swipeMenuView(_ swipeMenuView: SwipeMenuView, viewControllerForPageAt index: Int) -> UIViewController { let viewController = TableViewController() viewController.delegate = self addChild(viewController) return viewController } // テーブルをスクロールしたら呼ばれる // テーブルビューのスクロール位置からヘッダーのスクロール位置をセットする func receiveTableViewControllerScroll(_ offset: CGFloat) { let new = header.frame.origin.y + offset - 22 let max = header.frame.origin.y + header.frame.size.height - 22 let now = scrollView.contentOffset.y if new < max { scrollView.setContentOffset(CGPoint(x: 0, y: new), animated: false) } else if now < new { scrollView.setContentOffset(CGPoint(x: 0, y: max), animated: false) } } }
TableViewController.swift
import UIKit class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { weak var delegate: TableViewControllerProtocol? var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView = UITableView(frame: CGRect(x:0, y:0, width:view.frame.width, height:view.frame.height)) tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") tableView.delegate = self tableView.dataSource = self tableView.showsVerticalScrollIndicator = false tableView.bounces = false self.view.addSubview(tableView) } private func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return 60 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 100 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) cell.textLabel?.text = String(format: "行番号:%d", indexPath.row) return cell } // スクロール位置を親のViewControllerに通知 func scrollViewDidScroll(_ scrollView: UIScrollView) { delegate?.receiveTableViewControllerScroll(tableView.contentOffset.y) } } protocol TableViewControllerProtocol: class { func receiveTableViewControllerScroll(_ offset: CGFloat) -> Void }
課題
・行数が少ない場合にバグる
・ヘッダー部分をスクロールした場合に子のスクロール位置も調整するべき
だれか修正してソース共有してください。以上です