我的水平 collectionView 中有 5 张图像,它看起来像旋转木马,一个单元格与其他单元格重叠。另外,我有一个 UIPageControl 和下一个/上一个按钮,用于更改轮播项目。
class ViewController:
UIViewController,
UICollectionViewDelegate,
UICollectionViewDataSource {
@IBOutlet private var collectionView: UICollectionView!
@IBOutlet private var nextButton: UIButton!
@IBOutlet private var previousButton: UIButton!
@IBOutlet private var pageControl: UIPageControl!
let images: [UIImage] = [
image1,
image2,
image3,
image4,
image5,
]
var currentPage: Int = 0 {
didSet {
pageControl.currentPage = currentPage
}
}
在 viewDidLoad 方法中,我将 pageControl 项目设置为:
override func viewDidLoad() {
collectionView.delegate = self
collectionView.dataSource = self
previousButton.isHidden = true
nextButton.isEnabled = true
pageControl.numberOfPages = images.count
pageControl.currentPage = 0
pageControl.clipsToBounds = false
}
在使用下一个/上一个按钮在 collectionView 中显示轮播项目时效果很好。但问题是 currentPage 状态没有为 scrollViewDidEndDecelerating 方法更新,并且在使用下一个/上一个按钮进行一些遍历后,它会自动滚动到 collectionView 的第一个单元格或最后一个单元格,并且 currentPage 状态令人困惑。
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = ceil(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
currentPage = Int(pageNumber)
updateButtonStates(with: currentPage)
updateUI(with: currentPage)
}
@IBAction func didTapOnPreviousButton(_ sender: Any) {
if currentPage > 0 {
currentPage -= 1
print("IndexPath(item: currentPage, section: 0)", IndexPath(item: currentPage, section: 0))
collectionView?.isPagingEnabled = false
collectionView.scrollToItem(
at: IndexPath(item: currentPage,
section: 0),
at: .centeredHorizontally,
animated: true)
collectionView?.isPagingEnabled = true
pageControl.currentPage = currentPage
updateButtonStates(with: currentPage)
updateUI(with: currentPage)
}
}
@IBAction func didTapNextButton(_ sender: Any) {
if currentPage < images.count - 1 {
currentPage += 1
print("IndexPath(item: currentPage, section: 0)", IndexPath(item: currentPage, section: 0))
collectionView?.isPagingEnabled = false
collectionView.scrollToItem(
at: IndexPath(item: currentPage,
section: 0),
at: .centeredHorizontally,
animated: true)
collectionView?.isPagingEnabled = true
pageControl.currentPage = currentPage
updateButtonStates(with: currentPage)
updateUI(with: currentPage)
}
}
private func updateUI(with currentPage: Int) {
pageControl.currentPage = currentPage
previousButton.isHidden = currentPage == 0
nextButton.isHidden = currentPage == images.count - 1
}
func updateButtonStates(with currentPage: Int) {
pageControl.currentPage = currentPage
previousButton.isEnabled = currentPage > 0
nextButton.isEnabled = currentPage < images.count
}
我想要做的是当用户在单元格之间滚动然后单击下一个/上一个按钮时,pageControl 状态对于两个不同的操作应该相同。
这就是我解决问题的方法:
我使用 scrollViewWillEndDragging 方法来获取 scrollView 的精确点和 collectionView 的当前 itemWidth。
func scrollViewWillEndDragging(
_: UIScrollView,
withVelocity _: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>
) {
let offset = targetContentOffset.pointee.x
let widthPerItem = collectionView.bounds.width / images.count
pageControl.currentPage = Int(floor(offset / widthPerItem))
updateButtonStates(with: pageControl.currentPage)
updateUI(with: pageControl.currentPage)
}
还使用 IBAction 更新更新了 UI 和下一个/上一个按钮状态:
@IBAction
func didTapOnPreviousButton(_: Any) {
let prevIndex = max(pageControl.currentPage - 1, 0)
let indexPath = IndexPath(item: prevIndex, section: 0)
pageControl.currentPage = prevIndex
collectionView?.isPagingEnabled = false
collectionView.scrollToItem(
at: indexPath,
at: .centeredHorizontally,
animated: true
)
updateButtonStates(with: pageControl.currentPage)
updateUI(with: pageControl.currentPage)
}
@IBAction
func didTapOnNextButton(_: Any) {
let nextIndex = min(pageControl.currentPage + 1, images.count - 1)
let indexPath = IndexPath(item: nextIndex, section: 0)
pageControl.currentPage = nextIndex
collectionView?.isPagingEnabled = false
collectionView.scrollToItem(
at: indexPath,
at: .centeredHorizontally,
animated: true
)
updateButtonStates(with: pageControl.currentPage)
updateUI(with: pageControl.currentPage)
}
简而言之,
pageControl.currentPage
状态应该在相应的方法中更新,例如下一个/上一个按钮操作和滚动视图。