【问题标题】:How to add pagination in UICollectionView in swift?如何在 UICollectionView 中快速添加分页?
【发布时间】:2018-07-11 09:41:58
【问题描述】:

我有一个显示项目的 UICollection 视图。现在我想在 UICollectionView 上添加分页。我不想为此功能使用任何第三方。请告诉我如何实现这一目标!

我有四个一例http://slicode.com/bottom-refresh-control-uicollectionview/

但在此我必须向上拖动滚动视图几秒钟才能使其工作。

【问题讨论】:

  • 检查collectionView contentOffset,如果滚动到达底部则调用下一页。您也可以以编程方式开始刷新 refreshControl。
  • 你能提供一些代码吗?
  • 你的问题解决了吗?
  • 是的,我接受了你的回答。学习这些课程超级简单

标签: ios swift xcode uicollectionview


【解决方案1】:

简单的方法

 var page: Int = 0
 var isPageRefreshing:Bool = false

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    YourApi(page1: 0)
}

 func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if(self.mycollectionview.contentOffset.y >= (self.mycollectionview.contentSize.height - self.mycollectionview.bounds.size.height)) {
        if !isPageRefreshing {
            isPageRefreshing = true
            print(page)
            page = page + 1
            YourApi(page1: page)
        }
    }
}

在您的 api 方法中

func YourApi(page1: Int) {
    let mypage = String(page1)
    let request: String = String.init(format:"apiName/%@", mypage)
    print(request)
}

就是这样。

【讨论】:

    【解决方案2】:

    如果你想添加底部刷新控件,你必须使用下面的帮助类。

    https://github.com/vlasov/CCBottomRefreshControl/tree/master/Classes

    下载这两个在 Objective-C 中的文件。您必须在桥接头中导入此文件

    #import "UIScrollView+BottomRefreshControl.h"
    

    像这样添加刷新控件。

    let refreshControl = UIRefreshControl.init(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
    refreshControl.triggerVerticalOffset = 50.0 
    refreshControl.addTarget(self, action: #selector(paginateMore), for: .valueChanged) 
    collectionView.bottomRefreshControl = refreshControl
    

    这个帮助类为您提供了新的bottomRefreshControl 属性,它可以帮助您在底部添加刷新控件。

    【讨论】:

    • 这里 fetchNextData() 与刷新的关系。应该调用哪个方法
    • @Techiee 将 #selector(refresh) 替换为 #selector(fetchNextData) 可能对您有用。
    • 我在集合视图中添加了刷新控件作为子视图,但它没有显示在页脚中。它显示为集合视图顶部作为拉刷新
    • @Techiee 你是只滚动垂直/水平方向还是双向滚动
    • 仅垂直方向
    【解决方案3】:

    我已经在我的一个应用程序中添加了加载更多功能,所以让我给你代码

        func collectionView(_ collectionView: UICollectionView, layout
            collectionViewLayout: UICollectionViewLayout,
                            referenceSizeForFooterInSection section: Int) -> CGSize {
    
            if arrData.count > 0 && isLastPageReached == false
            {
                return CGSize(width:(collectionView.frame.size.width), height: 100.0)
            }
            return CGSize.zero
    
        }
        func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    
            if kind == UICollectionElementKindSectionFooter {
    
                let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: "footer", for: indexPath)
    
    
                let loading = UIActivityIndicatorView()
                loading.activityIndicatorViewStyle = .gray
                loading.translatesAutoresizingMaskIntoConstraints = false
                loading.tintColor = UIColor.gray
                loading.tag = -123456
                view.addSubview(loading)
                view.addConstraint(NSLayoutConstraint(item: loading, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1, constant: 0))
                vew.addConstraint(NSLayoutConstraint(item: loading, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0))
    
    
                return view
            }
            return UICollectionReusableView()
        }
    
        func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) {
            if elementKind == UICollectionElementKindSectionFooter {
    
                if let loadingView = view.viewWithTag(-123456) as? UIActivityIndicatorView{
                    if arrData.count > 0 && isLastPageReached == false 
                    {
                        loadingView.startAnimating()
                        self.loadMore()
                    }
                    else
                    {
                        self.isLoadMore = false
                    }
                }
            }
        }
        func collectionView(_ collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, at indexPath: IndexPath) {
            if elementKind == UICollectionElementKindSectionFooter{
    
                if let loadingView = view.viewWithTag(-123456) as? UIActivityIndicatorView{
                    loadingView.stopAnimating()
                    loadingView.removeFromSuperview()
    
                    self.isLoadMore = false
                }
    
            }
        }
    

    【讨论】:

    • 如何维护 isLastPageReached ?这个函数用在哪里 self.removeLoadMoreView ?
    • @Techiee 你需要在 api 响应中管理的布尔值。如果两者相同,我得到页面总数和当前页面,那么 bool 将变为 true,否则为 false 这个函数在哪里使用 self.removeLoadMoreView ? - 让我编辑我的答案
    • 请问您定义了哪些常量?例如isLoadMore
    【解决方案4】:

    请试试这个对我有用。

    第 1 步:

    声明一个全局变量:

    var totalCount : NSInteger?
    var isGetResponse : Bool = true
    var activityIndiator : UIActivityIndicatorView?
    

    设置viewDidLoad:

    activityIndiator = UIActivityIndicatorView(frame: CGRect(x: self.view.frame.midX - 15, y: self.view.frame.height - 140, width: 30, height: 30))
        activityIndiator?.activityIndicatorViewStyle = .white
        activityIndiator?.color = UIColor.black
        activityIndiator?.hidesWhenStopped = true
        activityIndiator?.backgroundColor = COLOR.COLOR_TABLEVIEW_BACKGROUND
        activityIndiator?.layer.cornerRadius = 15
        self.view.addSubview(activityIndiator!)
        self.view.bringSubview(toFront: activityIndiator!)
    

    第 2 步: 在api调用方法中设置值:

    self.totalCount = array.count
    self.isGetResponse = true
    

    第 3 步: 写下这段代码:

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
    
    if isGetResponse {
        if (scrollView.contentOffset.y == scrollView.contentSize.height - scrollView.frame.size.height)
        {
            if totalArrayCount! > self.arrProductListing.count{
    
                    isGetResponse = false
                    activityIndiator?.startAnimating()
                    self.view.bringSubview(toFront: activityIndiator!)
                    pageIndex = pageIndex + 1
                    print(pageIndex)
                    self.getProductListing(withPageCount: pageIndex)
                }
            }
    
            //LOAD MORE
            // you can also add a isLoading bool value for better dealing :D
        }
    }
    

    在服务调用中,您可以发送页面索引,然后从服务器端返回响应。

    谢谢。

    【讨论】:

    • 你在哪里定义 totalArrayCountpageIndex 这个解决方案看起来不错,但很混乱
    • 谢谢,对我来说最好使用scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height
    【解决方案5】:

    CollectionView 委托方法:在 CollectionView 上加载更多关于 Scroll Demand 的数据。

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
            if indexPath.row == numberofitem.count - 1 {  //numberofitem count
                updateNextSet()  
            }
    }
    
    func updateNextSet(){
           print("On Completetion")
           //requests another set of data (20 more items) from the server.
    }
    

    【讨论】:

      【解决方案6】:

      以下两个函数负责分页。如下所示。

          override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
          if current_page < total_page && indexPath.row == cars.count - 1 {
              let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "loading_cell", for: indexPath) as! PaginationCollectionViewCell
              cell.actIndicator.startAnimating()
      
              return cell
          }else {
              let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! PaginationCollectionViewCell
              cell.lbTitle.text = cars[indexPath.row].company_name
              cell.lbDescription.text = cars[indexPath.row].engine_power
              return cell
          }
      }
      
      override func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
          if current_page < total_page && indexPath.row == cars.count - 1 {
              current_page = current_page + 1
              DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
                  self.fetchData(page: self.current_page)
              }
          }
      }
      

      【讨论】:

        【解决方案7】:

        我在进行分页时使用了该代码。 重点是;在集合视图加载时捕获加载的单元格索引,并使用数字控制它的 mod,并使用 api 中的页面大小字段单独获取数据(如果有)。您可以决定哪个数字将小于此计算,并且您将控制它。

        例如,您获取了 5 个数据并加载了它,如果此状态正常,您将获取其他 5 个。这是示例代码。

        func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
                if let vc = self.parentViewController as? SellController {
                    if vc.dontFetch == false {
                        DispatchQueue.main.async {
                            if self.salesData.count > 3 {
                                if indexPath.row != 1 {
                                    if indexPath.row % 3 == 1 {
                                        print("indexpath: \(indexPath.row)")
                                        vc.pagination += 1
                                        vc.reload()
        
                                    }
                                }
                            }
                        }
                    }
                }
            }
        

        在这段代码中,我控制 indexpath.row % 3 == 1 与否。它可能有点复杂,所以如果你愿意,我可以分享一个代码块。祝你好运:)

        【讨论】:

          【解决方案8】:

          -- itemList - 你的数据数组。

          -- pageCount - 用于跟踪页数的变量。

          -- totalCount - 数据总数

          --- 每次调用 API 时将数据附加到 itemList

          func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
              if indexPath.row == itemList.count - 1 && itemList.count < totalCount{
                  pageCount += 1
                  // Call API here
              }
          }
          

          【讨论】:

            【解决方案9】:

            willDisplay cell 方法中的代码调用 load more 函数,而您的滚动条距离末端 5 个单元格。获取数据时在集合视图页脚中显示加载程序。加载完成后隐藏页脚。

            func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {        
                    let currentPage = collectionView.contentOffset.y / collectionView.frame.size.width;
                    if (aryDataSource.count >= yourAPIResponsebatchCount && aryDataSource.count - indexPath.row == 5 && currentPage >= currentPage && isDataLoading) {
                        currentPage++;
                        self.fetchMoreData()
                    }
                    else { }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-09-13
              • 1970-01-01
              • 2019-10-24
              • 1970-01-01
              • 1970-01-01
              • 2015-07-12
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多