やりたいこと
- ズーム、スクロールをしつつヘッダー部を固定したい
- 過去に投稿したUICollectionViewでExcelライクなUIを作成するではズームが出来ないため、不採用
どうすれば良いか
UIScrollViewの子Viewに固定したいViewを配置し、ズームとスクロール時に座標を更新すれば解決!
コード
import UIKit
class ViewController: UIViewController {
/// UIScrollView
@IBOutlet weak var scrollView: UIScrollView! {
didSet {
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 5.0
}
}
/// UIScrollViewでズームさせるView
@IBOutlet weak var zoomView: UIView!
/// ヘッダーView
@IBOutlet weak var headerView: UIView!
// 座標を更新する
func updateHeaderViewOrigin(_ scrollView: UIScrollView) {
// スクロールさせている位置にY座標を移動する
headerView.frame.origin.y = scrollView.contentOffset.y / scrollView.zoomScale
}
}
// MARK: UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate {
func scrollViewDidZoom(_ scrollView: UIScrollView) {
updateHeaderViewOrigin(scrollView)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderViewOrigin(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
zoomView
}
}
注意点
固定させるViewは必ず最前面に表示する
(スクロール時に後ろへいってしまうため、固定されている様にみえない)
応用
列のみを固定したい場合
列Viewを作成し、x座標を変更する
func updateHeaderViewOrigin(_ scrollView: UIScrollView) {
firstColumn.frame.origin.x = scrollView.contentOffset.x / scrollView.zoomScale
}
Excelのような枠固定したい場合
列View/行View/枠固定Viewを作成し、それぞれ座標を更新する
func updateHeaderViewOrigin(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x / scrollView.zoomScale
let y = scrollView.contentOffset.y / scrollView.zoomScale
// 先頭行
headerView.frame.origin.y = y
// 先頭列
firstColumnView.frame.origin.x = x
// 固定枠
frozenPaneView.frame.origin.x = x
frozenPaneView.frame.origin.y = y
}