背景
例によって、個人開発したScoreBoxという麻雀成績管理アプリからのネタ。
本アプリのコア機能となる成績管理の入力は表形式になります。
大きく分けると、成績を蓄積する部分、合計値を表す部分の2つ。
性質が異なるため1つの表での表現は難しく、今回は2つの表に分けることにしました。
なお、表のコントロールにはSpreadsheetViewを利用させていただきました。
ありがとうございます。
悩んだ
表を分けるようにしたのはいいものの、
ScrollViewのスクロール検知はdelegateが紐づいている1つのViewでしか有効でないので、
AのViewをスクロールしたからといって、勝手にBのViewも一緒にスクロールはしてくれません。
そこで、AのViewのスクロールを検知したら、他のViewもスクロールを同期させる工夫が必要でした。
工夫した
- UIScrollViewDelegate
- NotificationCenter
を利用しました。
import UIKit
import SpreadsheetView
class GameDetailViewController: BaseViewController {
// (A View)成績を蓄積する部分
@IBOutlet weak var scoreSheetView: SpreadsheetView!
// (B View)合計値を表す部
@IBOutlet weak var sumSheetView: SpreadsheetView!
override func viewDidLoad() {
super.viewDidLoad()
// 表コントロールのScrollViewへ Delegate を紐付ける
scoreSheetView.scrollView.delegate = self
sumSheetView.scrollView.delegate = self
// スクロール同期を実行する通知イベントを登録する
NotificationCenter.default.addObserver(self, selector: #selector(receiveScrollNotification(notification:)), name: .tableScroll, object: nil)
}
// スクロール同期する
@objc func receiveScrollNotification(notification: NSNotification) {
guard let scrollView = notification.object as? UIScrollView else {
return
}
// 先にスクロールしたViewのスクロール位置を、他のViewに追従させる
if scrollView == scoreSheetView.scrollView {
sumSheetView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: sumSheetView.scrollView.contentOffset.y), animated: false)
}else{
scoreSheetView.setContentOffset(CGPoint(x: scrollView.contentOffset.x, y: sumSheetView.scrollView.contentOffset.y), animated: false)
}
}
}
extension GameDetailViewController : UIScrollViewDelegate {
// あるViewのスクロールを検知したら、他のViewも一緒にスクロールするよう通知する
func scrollViewDidScroll(_ scrollView: UIScrollView) {
NotificationCenter.default.post(name: .tableScroll, object: scrollView)
}
}
実際の画面
その他
今回は横スクロールの同期だけでしたが、縦スクロールも同期可能です。