Skip to content

Instantly share code, notes, and snippets.

@kishikawakatsumi
Created April 29, 2018 15:21
Show Gist options
  • Save kishikawakatsumi/227ad300f0704f9323984265150ce0d8 to your computer and use it in GitHub Desktop.
Save kishikawakatsumi/227ad300f0704f9323984265150ce0d8 to your computer and use it in GitHub Desktop.
UIScrollView + UIPageControl with RxSwift
import RxSwift
import RxCocoa
fileprivate extension Reactive where Base: UIScrollView {
fileprivate var currentPage: Observable<Int> {
return didEndDecelerating.map({
let pageWidth = self.base.frame.width
let page = floor((self.base.contentOffset.x - pageWidth / 2) / pageWidth) + 1
return Int(page)
})
}
}
fileprivate extension UIScrollView {
fileprivate func setCurrentPage(_ page: Int, animated: Bool) {
var rect = bounds
rect.origin.x = rect.width * CGFloat(page)
rect.origin.y = 0
scrollRectToVisible(rect, animated: animated)
}
}
class ViewController: UIViewController {
private let disposeBag = DisposeBag()
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var pageControl: UIPageControl!
override func viewDidLoad() {
super.viewDidLoad()
pageControl.rx.controlEvent(.valueChanged)
.subscribe(onNext: { [weak self] in
guard let currentPage = self?.pageControl.currentPage else {
return
}
self?.scrollView.setCurrentPage(currentPage, animated: true)
})
.disposed(by: disposeBag)
scrollView.rx.currentPage
.subscribe(onNext: { [weak self] in
self?.pageControl.currentPage = $0
})
.disposed(by: disposeBag)
scrollView.isPagingEnabled = true
scrollView.contentSize = CGSize(width: scrollView.bounds.width * 4, height: scrollView.bounds.height)
}
}
@markst
Copy link

markst commented Jan 23, 2020

can also be bound as:

scrollView.rx.currentPage
  .bind(to: pageControl.rx.currentPage)
  .disposed(by: disposeBag)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment