简体   繁体   English

如何在 UICollectionView 中快速添加分页?

[英]How to add pagination in UICollectionView in swift?

I have a UICollection view which shows items.我有一个显示项目的 UICollection 视图。 Now I want to add pagination on UICollectionView.现在我想在 UICollectionView 上添加分页。 I do not want to use any third party for this functionality.我不想为此功能使用任何第三方。 Please let me know how I can achieve this!请让我知道如何实现这一目标!

I have four one example http://slicode.com/bottom-refresh-control-uicollectionview/我有四个一个例子http://slicode.com/bottom-refresh-control-uicollectionview/

But in this I have to drag scrollview upwards for few second to make it work.但在此我必须向上拖动滚动视图几秒钟才能使其工作。

Easy way to do that简单的方法来做到这一点

 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)
        }
    }
}

In your api methods在您的 api 方法中

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

That's it.而已。

If you want to add bottom refresh control you have to use below helper class.如果要添加底部刷新控件,则必须使用下面的帮助程序类。

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

Download this 2 files which is in Objective-C.下载Objective-C中的这2个文件。 You have to import this file in Bridging header您必须在桥接头中导入此文件

#import "UIScrollView+BottomRefreshControl.h"

Add refresh control like this.像这样添加刷新控件。

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

This helper class provide you new bottomRefreshControl property, which helps you to add refresh control in bottom.这个帮助类为你提供了新的bottomRefreshControl属性,它可以帮助你在底部添加刷新控件。

I have added the functionality of load more in one of my application so let me give you the code我在我的一个应用程序中添加了加载更多功能,所以让我给你代码

    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
            }

        }
    }

Please try this it works for me.请试试这个它对我有用。

Step 1:步骤1:

Declare a global variable :声明一个全局变量:

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

Set the viewDidLoad:设置 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!)

Step 2: Set the value in the api call method:第二步:在api调用方法中设置值:

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

Step 3: Write this code :第 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
    }
}

In service call you can send the page index and from the server end they send back the response.在服务调用中,您可以发送页面索引并从服务器端发回响应。

Thank you.谢谢你。

CollectionView Delegate method: Load More data on Scroll Demand on CollectionView. CollectionView 委托方法:在 CollectionView 上加载更多关于滚动需求的数据。

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.
}

The following two function are responsible for the pagination.以下两个函数负责分页。 As you can see below.正如你在下面看到的。

    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)
        }
    }
}

I used that code while doing pagination.我在进行分页时使用了该代码。 The point is;重点是; catching the loaded cell index while collection view is loading and control it's mod with a number and fetch datas seperately with page size field in the api (if there is).在集合视图加载时捕获加载的单元格索引,并使用数字控制它的 mod,并使用 api 中的页面大小字段单独获取数据(如果有)。 You can decide which number will be smaller than this calculation and you will control it.您可以决定哪个数字将小于此计算,并且您将控制它。

For example you fetched 5 datas and loaded it and, if this state is ok, you will fetch the other 5. Here is the sample code for that.例如,您获取了 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()

                            }
                        }
                    }
                }
            }
        }
    }

In this code i am controlling indexpath.row % 3 == 1 or not.在这段代码中,我控制 indexpath.row % 3 == 1 与否。 It can be little bit complex so i can share a code block if you want.它可能有点复杂,所以如果你愿意,我可以分享一个代码块。 Good luck:)祝你好运:)

-- itemList - your data array. -- itemList - 你的数据数组。

-- pageCount - variable used to keep track of the number of pages. -- pageCount - 用于跟踪页数的变量。

-- totalCount - total number of data -- totalCount - 数据总数

--- append data to itemList every time you call the API. --- 每次调用 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
    }
}

The code in willDisplay cell method calls load more function while your scroll is 5 cells away from the end. willDisplay cell方法中的代码调用 load more 函数,而您的滚动距离末端 5 个单元格。 While fetching data show loader in collection view footer.获取数据时在集合视图页脚中显示加载程序。 Hide footer when loading is completed.加载完成后隐藏页脚。

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 { }
}

I walk through all answers in this thread and all seems a bit complex to implement.我浏览了这个线程中的所有答案,所有答案似乎都实现起来有点复杂。 My situation required a collection view pagination where a page had the same width as the screen width, for this particular case the solution is:我的情况需要一个集合视图分页,其中页面的宽度与屏幕宽度相同,对于这种特殊情况,解决方案是:

collectionView.isPagingEnabled = true

I am not 100% sure if this works for the case when a page width is different than screen width.我不是 100% 确定这是否适用于页面宽度与屏幕宽度不同的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM