[英]How to put UICollectionView and button in UIPageControl in ios?
[英]iOS6 UICollectionView and UIPageControl - How to get visible cell?
在學習 iOS6 新功能時,我有一個關於UICollectionView的問題。
我目前正在使用 Flow 布局和滾動方向設置為水平、滾動和分頁來測試它。 我已將其大小設置為與我自定義的單元格完全相同,因此它可以一次顯示一個,並且通過將其向側面滾動,用戶將看到其他現有單元格。
它完美地工作。
現在我想將UIPageControl添加到我創建的集合視圖中,以便它可以顯示哪個單元格可見以及有多少個單元格。
構建頁面控件相當簡單,frame 和 numberOfPages 已定義。
正如問題標題所標記的,我遇到的問題是如何獲取當前在集合視圖中可見的單元格,以便它可以更改頁面控件的 currentPage。
我試過委托方法,比如 cellForItemAtIndexPath,但它是用來加載單元格的,而不是顯示它們。 didEndDisplayingCell 在單元格不再顯示時觸發,這是我需要的相反事件。
看起來集合視圖方法 -visibleCells 和 -indexPathsForVisibleItems 是我的正確選擇,但我遇到了另一個問題。 什么時候觸發它們?
在此先感謝,希望我說得足夠清楚,以便你們能理解我!
您必須將自己設置為UIScrollViewDelegate
並實現scrollViewDidEndDecelerating:
方法,如下所示:
目標-C
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth;
}
迅速
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = self.collectionView.frame.size.width
pageControl.currentPage = Int(self.collectionView.contentOffset.x / pageWidth)
}
我也為此掙扎了一段時間,然后我被建議檢查 UICollectionView 的父類。 其中之一恰好是UIScrollView ,如果您將自己設置為UIScrollViewDelegate ,您就可以訪問非常有用的方法,例如scrollViewDidEndDecelerating ,這是更新 UIPageControl 的好地方。
我建議稍微調整計算和處理,因為它會在任何滾動位置立即更新頁面控制,並具有更高的准確性。
下面的解決方案適用於任何滾動視圖或其子類(UITableView UICollectionView 等)
在 viewDidLoad 方法中寫這個
scrollView.delegate = self
然后使用您的語言代碼:
斯威夫特 3
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
let pageWidth = scrollView.frame.width
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
斯威夫特 2:
func scrollViewDidScroll(scrollView: UIScrollView)
{
let pageWidth = CGRectGetWidth(scrollView.frame)
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
目標 C
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth;
}
另一個代碼較少的選項是使用可見項索引路徑並設置頁面控件。
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row];
}
int pages =floor(ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages:pages];
添加ScrollView 委托方法,
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = ImageCollectionView.frame.size.width;
float currentPage = ImageCollectionView.contentOffset.x / pageWidth;
if (0.0f != fmodf(currentPage, 1.0f))
{
pageControl.currentPage = currentPage + 1;
}
else
{
pageControl.currentPage = currentPage;
}
NSLog(@"finishPage: %ld", (long)pageControl.currentPage);
}
我知道這是一個舊的,但我只需要再次實現這種功能並添加一些內容以提供更完整的答案。
首先:使用scrollViewDidEndDecelerating
假設用戶在拖動時抬起手指(更像是輕彈動作),因此存在減速階段。 如果用戶在不抬起手指的情況下進行拖動, UIPageControl
仍將指示拖動開始之前的舊頁面。 相反,使用scrollViewDidScroll
回調意味着視圖在拖動和輕彈之后以及在拖動和滾動期間都會更新,因此對用戶來說感覺更加靈敏和准確。
其次:依托pagewidth
,用於計算所選索引假定所有單元具有相同的寬度,並且有每屏一個小區。 取的優點indexPathForItemAtPoint
上方法UICollectionView
給出了一個更有彈性的結果,這將對於不同的布局和小區大小工作。 下面的實現假設框架的中心是要在pagecontrol
表示的所需單元格。 此外,如果在滾動期間有單元格間距,則 selectedIndex 可能為零或可選,因此需要在設置 pageControl 之前檢查和展開。
func scrollViewDidScroll(scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset
let centrePoint = CGPointMake(
contentOffset.x + CGRectGetMidX(scrollView.frame),
contentOffset.y + CGRectGetMidY(scrollView.frame)
)
if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){
self.pageControl.currentPage = index.row
}
}
還有一件事 - 使用以下內容設置UIPageControl
上的UIPageControl
:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
self.pageControl.numberOfPages = 20
return self.pageControl.numberOfPages
}
簡單的斯威夫特
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)!
}
如果你實現了UICollectionViewDelegate
就已經實現了UIScrollViewDelegate
如果使用scrollViewDidScroll
,則應手動更新頁面控件以 ⚠️避免點擊頁面控件時出現閃爍的點。
設置UIPageControl
。
let pageControl = UIPageControl()
pageControl.pageIndicatorTintColor = .label
pageControl.defersCurrentPageDisplay = true // Opt-out from automatic display
pageControl.numberOfPages = viewModel.items.count
pageControl.addTarget(self, action: #selector(pageControlValueChanged), for: .valueChanged)
實施操作(使用下面的擴展)。
@objc func pageControlValueChanged(_ sender: UIPageControl) {
collectionView.scroll(to: sender.currentPage)
}
在每次滾動時手動更新UIPageControl
。
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
pageControl.currentPage = collectionView.currentPage
pageControl.updateCurrentPageDisplay() // Display only here
}
}
UICollectionView
擴展。
extension CGRect {
var middle: CGPoint {
CGPoint(x: midX, y: midY)
}
}
extension UICollectionView {
var visibleArea: CGRect {
CGRect(origin: contentOffset, size: bounds.size)
}
var currentPage: Int {
indexPathForItem(at: visibleArea.middle)?.row ?? 0
}
func scroll(to page: Int) {
scrollToItem(
at: IndexPath(row: page, section: 0),
at: .centeredHorizontally,
animated: true
)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.