2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Swift]複数のScrollViewのスクロールを同期する

Last updated at Posted at 2020-05-30

背景

例によって、個人開発した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)
    }
}

実際の画面

20200531_022339.GIF

その他

今回は横スクロールの同期だけでしたが、縦スクロールも同期可能です。

2
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?