I have a UIScrollView with 10 pages. I am able to flick between them. I also want to have 2 buttons (a back button and a next button) which when touched will go to the previ
If scrollRectToVisible doesn't work try this :
let frame = scrollView.frame
let offset:CGPoint = CGPoint(x: CGFloat(sender.currentPage) * frame.size.width, y: 0)
self.scrollView.setContentOffset(offset, animated: true)
Additional to this code that mjdth added, remember to place it in the viewWillAppear or viewDidAppear.
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * pageNumberYouWantToGoTo;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:YES];
First create a UIScrollView extension like:
extension UIScrollView {
func setCurrentPage(position: Int) {
var frame = self.frame;
frame.origin.x = frame.size.width * CGFloat(position)
frame.origin.y = 0
scrollRectToVisible(frame, animated: true)
}
}
then just call:
self.scrollView.setCurrentPage(position: 2) // where 2 is your desired page
I wanted to implement an image slider with automatic scrolling using a UIScrollView and a UIStackView. This is what I ended up with and it's working pretty well. I a using PureLayout for AutoLayout:
class ImageSlideShow: UIView {
private let scrollView = UIScrollView()
private var images: [UIImage] = []
private var scrollTimer: Timer?
init() {
super.init(frame: .zero)
self.setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func setImages(_ images: [UIImage], initialIndex: Int = 0) {
self.images = images
self.scrollTimer?.invalidate()
self.scrollView.removeAllSubviews()
let stackView = self.getStackView()
self.scrollView.addSubview(stackView)
stackView.autoMatch(.height, to: .height, of: self.scrollView)
stackView.autoPinEdgesToSuperviewEdges()
self.images.forEach { image in
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
stackView.addArrangedSubview(imageView)
imageView.autoMatch(.width, to: .width, of: self.scrollView)
}
self.setupScrollTimer()
}
private func getStackView() -> UIStackView {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .fill
stackView.distribution = .equalSpacing
stackView.spacing = 0
return stackView
}
private func setupScrollTimer() {
self.scrollTimer = Timer.scheduledTimer(
timeInterval: 0.5,
target: self,
selector: #selector(scroll), userInfo: nil,
repeats: true
)
}
@objc private func scroll() {
let currentPage = self.scrollView.contentOffset.x / scrollView.frame.size.width
var nextPage = currentPage + 1
var frame: CGRect = self.scrollView.frame
if nextPage >= CGFloat(self.images.count) {
nextPage = 0
}
frame.origin.x = frame.size.width * CGFloat(nextPage)
self.scrollView.scrollRectToVisible(frame, animated: true)
}
private func setupView() {
self.backgroundColor = Colors.cream
self.setupScrollView()
}
private func setupScrollView() {
self.addSubview(self.scrollView)
self.scrollView.autoPinEdgesToSuperviewEdges(with: .margin(Metrics.paddingDoublePlus))
self.scrollView.isPagingEnabled = true
self.scrollView.layer.cornerRadius = Metrics.cornerRadius
self.scrollView.showsHorizontalScrollIndicator = false
self.scrollView.showsVerticalScrollIndicator = false
}
}
func changePage(pageControl: UIPageControl) {
let page = CGFloat(pageControl.currentPage)
var frame = self.scrollView.frame
frame.origin.x = frame.size.width * page
frame.origin.y = 0
self.scrollView.scrollRectToVisible(frame, animated: true)
}
scrollRectToVisible was not working for me, so I had to animate the contentOffset. This code works in swift 3.
func scrollToPage(_ page: Int) {
UIView.animate(withDuration: 0.3) {
self.scrollView.contentOffset.x = self.scrollView.frame.width * CGFloat(page)
}
}