Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 스크롤 방향 확인 방법 (UIScrollView, RxSwift) 본문

iOS 응용 (swift)

[iOS - swift] 스크롤 방향 확인 방법 (UIScrollView, RxSwift)

jake-kim 2023. 2. 23. 18:24

scroll 방향(= indicator 방향) 확인

스크롤 방향 구하기 아이디어

  • scroll 방향의 기준은 indicator 의 방향과 동일하게 기준을 설정 (indicator가 내려가면 스크롤 방향이 down이라고 정의)
  • pan gesture를 확인하면 스크롤을 어느 방향으로 하고 있는지 판단이 매우 쉬우므로, pan gesture 값을 사용
  • 여러곳에서 사용되기 때문에 UIScrollView의 extension으로 정의

스크롤 방향 구하기

  • 스크롤은 Rx와 같이 사용하면 편리하게 사용이 가능하므로 RxSwift, RxGesture 사용
target 'ExScrolling' do
  use_frameworks!

  pod 'RxSwift'
  pod 'RxGesture'
end
  • 스크롤 확인을 위한 UI 준비
    • tableView 한개와 label이 있어서, 방향에 따라 label의 색상과 텍스트를 변경
import UIKit
import RxSwift
import RxGesture

class ViewController: UIViewController {
    private let label: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 20)
        label.textAlignment = .center
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    private let tableView: UITableView = {
        let view = UITableView()
        view.allowsSelection = false
        view.backgroundColor = .clear
        view.separatorStyle = .none
        view.contentInset = .zero
        view.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        view.estimatedRowHeight = 34
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()
    
    var items = (0...100).map(String.init)
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        
        view.addSubview(tableView)
        view.addSubview(label)
        
        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
        ])
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: view.topAnchor, constant: 56),
            label.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        items.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = items[indexPath.row]
        return cell
    }
}
  • pan gesture 사용
    • pan gesture 먼저 이해하기 - translation을 사용하면 in 파라미터에 들어간 좌표를 기준으로 제스쳐의 위치를 알려줌
    • 드래그를 시작할때 ss.tableView의 위치와 현재 드래그된 위치를 비교한 좌표를 의미
    • 단, 밑으로 갈 수록 +를 의미하고 위로 갈 수록 -를 의미
tableView.rx.panGesture()
    .bind(with: self) { ss, gesture in
        print(gesture.translation(in: ss.tableView).y)
    }
    .disposed(by: disposeBag)

  • 아래처럼 사용하면 스크롤 방향 확인에 용이
tableView.rx.panGesture()
    .bind(with: self) { ss, gesture in
        let isDown = gesture.translation(in: ss.tableView).y < 0
        ss.label.text = isDown ? "down" : "up"
        ss.label.textColor = isDown ? .red : .blue
    }
    .disposed(by: disposeBag)
  • 다른곳에서도 사용할 수 있도록 UIScrollView의 extension으로 추가
// extension으로 추가
extension Reactive where Base: UIScrollView {
    /// 오른쪽 indicator 방향 기준 (indicator가 내려가면 true)
    var isDownScrollable: Observable<Bool> {
        base.rx.panGesture()
            .withUnretained(base)
            .map { ss, gesture in
                gesture.translation(in: ss).y < 0
            }
    }
}

// 사용하는쪽
tableView.rx.isDownScrollable
    .bind(with: self) { ss, isDown in
        ss.label.text = isDown ? "down" : "up"
        ss.label.textColor = isDown ? .red : .blue
    }
    .disposed(by: disposeBag)

* 전체 코드: https://github.com/JK0369/ExScrollingDirection

Comments