Во многих приложениях вы можете столкнуться с прокруткой, которая никогда не переносится в противоположном направлении в конце контента. Эта техника стандартна уже в течение многих лет, на многих платформах. С другой стороны, есть много сторонних библиотек, чтобы получить этот эффект. НО вам не нужно никакой сторонней библиотеки. У этой техники очень простая логика.
Постраничная поддержка UIScrollView позволяет пользователю просматривать его содержимое постранично. UIScrollView включает этот эффект, регулируя смещение scrollView, когда пользователь заканчивает перетаскивание. Когда пользователь прокручивает до конца страниц (справа), scrollview ограничивает превышение его содержимого, перемещая его смещение в противоположном направлении с красивой анимацией.
Мы хотим, чтобы scrollview не ограничивал смещение содержимого, когда пользователь захочет превысить их количество. Поэтому нам нужно добавить еще две страницы в UIScrollView. Последняя страница будет добавлена ??в нулевой индекс, а первая страница будет добавлена ??в индекс (numberOfItems + 1). Затем, если пользователь просматривает страницу «numberOfItems», смещение содержимого прокрутки x устанавливается на 0. Если пользователь просматривает индекс 0, тогда смещение содержимого scrollView x будет установлено на «pageSize * numberOfItems».
Первое, что надо делать, — это создать новый класс, унаследованный от UIView.
BannerView должен быть как ниже:
import UIKit
class BannerView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
import UIKit
class BannerView: UIView {
private let scrollView:UIScrollView = {
let sc = UIScrollView(frame: .zero)
sc.translatesAutoresizingMaskIntoConstraints = false
sc.isPagingEnabled = true
return sc
}()
// BannerView DataSources (1)
private var itemAtIndex:((_ bannerView:BannerView , _ index:Int)->(UIView))!
private var numberOfItems:Int = 0
override init(frame: CGRect) {
super.init(frame: frame)
setUpUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setUpUI() {
scrollView.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
scrollView.delegate = self
self.addSubview(scrollView)
scrollView.showsHorizontalScrollIndicator = false
}
func reloadData(numberOfItems:Int , itemAtIndex:@escaping ((_ bannerView:BannerView , _ index:Int)->(UIView)) ) {
self.itemAtIndex = itemAtIndex
self.numberOfItems = numberOfItems
reloadScrollView()
}
private func reloadScrollView() {
guard self.numberOfItems > 0 else { return }
if self.numberOfItems == 1 {
let firstItem:UIView = self.itemAtIndex(self , 0)
addViewToIndex(view: firstItem, index: 0)
scrollView.isScrollEnabled = false
return
}
let firstItem:UIView = self.itemAtIndex(self , 0)
addViewToIndex(view: firstItem, index: numberOfItems+1)
let lastItem:UIView = self.itemAtIndex(self , numberOfItems-1)
addViewToIndex(view: lastItem, index: 0)
for index in 0..<self.numberOfItems {
let item:UIView = self.itemAtIndex(self , index)
addViewToIndex(view: item, index: index+1)
}
scrollView.contentSize = CGSize(width: CGFloat(numberOfItems+2)*scrollView.frame.size.width, height: scrollView.frame.size.height)
scrollView.contentOffset = CGPoint(x: self.scrollView.frame.size.width, y: self.scrollView.contentOffset.y)
}
private func addViewToIndex(view:UIView, index:Int) {
view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(view)
view.frame = CGRect(x: CGFloat(index)*scrollView.frame.size.width, y: 0, width: scrollView.frame.size.width, height: scrollView.frame.size.height)
}
}
// ViewController.swift
bannerView = BannerView(frame: CGRect(x: 0, y: 64, width: self.view.frame.size.width, height: 200))
self.view.addSubview(bannerView)
bannerView.reloadData(numberOfItems: 5) { (bannerView, index) -> (UIView) in
let view = UIView()
view.backgroundColor = UIColor.red
return view
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let currentPage:Int = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
if currentPage == 0 {
self.scrollView.contentOffset = CGPoint(x: scrollView.frame.size.width * CGFloat(numberOfItems), y: scrollView.contentOffset.y)
}
else if currentPage == numberOfItems {
self.scrollView.contentOffset = CGPoint(x: 0, y: scrollView.contentOffset.y)
}
}
// BannerView.swift
import UIKit
class BannerView: UIView , UIScrollViewDelegate{
private let scrollView:UIScrollView = {
let sc = UIScrollView(frame: .zero)
sc.translatesAutoresizingMaskIntoConstraints = false
sc.isPagingEnabled = true
return sc
}()
private var itemAtIndex:((_ bannerView:BannerView , _ index:Int)->(UIView))!
private var numberOfItems:Int = 0
override init(frame: CGRect) {
super.init(frame: frame)
setUpUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func reloadData(configuration:BannerViewConfiguration? , numberOfItems:Int , itemAtIndex:@escaping ((_ bannerView:BannerView , _ index:Int)->(UIView)) ) {
self.itemAtIndex = itemAtIndex
self.numberOfItems = numberOfItems
reloadScrollView()
}
private func reloadScrollView() {
guard self.numberOfItems > 0 else { return }
if self.numberOfItems == 1 {
let firstItem:UIView = self.itemAtIndex(self , 0)
addViewToIndex(view: firstItem, index: 0)
scrollView.isScrollEnabled = false
return
}
let firstItem:UIView = self.itemAtIndex(self , 0)
addViewToIndex(view: firstItem, index: numberOfItems+1)
let lastItem:UIView = self.itemAtIndex(self , numberOfItems-1)
addViewToIndex(view: lastItem, index: 0)
for index in 0..<self.numberOfItems {
let item:UIView = self.itemAtIndex(self , index)
addViewToIndex(view: item, index: index+1)
}
scrollView.contentSize = CGSize(width: CGFloat(numberOfItems+2)*scrollView.frame.size.width, height: scrollView.frame.size.height)
scrollView.contentOffset = CGPoint(x: self.scrollView.frame.size.width, y: self.scrollView.contentOffset.y)
}
private func addViewToIndex(view:UIView, index:Int) {
view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(view)
view.frame = CGRect(x: CGFloat(index)*scrollView.frame.size.width, y: 0, width: scrollView.frame.size.width, height: scrollView.frame.size.height)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let currentPage:Int = Int(scrollView.contentOffset.x / scrollView.frame.size.width)
if currentPage == 0 {
self.scrollView.contentOffset = CGPoint(x: scrollView.frame.size.width * CGFloat(numberOfItems), y: scrollView.contentOffset.y)
}
else if currentPage == numberOfItems {
self.scrollView.contentOffset = CGPoint(x: 0, y: scrollView.contentOffset.y)
}
}
private func setUpUI() {
scrollView.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
scrollView.delegate = self
self.addSubview(scrollView)
scrollView.showsHorizontalScrollIndicator = false
}
}
К сожалению, не доступен сервер mySQL