可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a UICollection view which shows items. Now I want to add pagination on 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/
But in this I have to drag scrollview upwards for few second to make it work.
回答1:
If you want to add bottom refresh control you have to use below helper class.
https://github.com/vlasov/CCBottomRefreshControl/tree/master/Classes
Download this 2 files which is in Objective-C. 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.
回答2:
CollectionView Delegate method: Load More data on Scroll Demand on 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.
}
回答3:
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
}
}
}
回答4:
Please try this it works for me.
Step 1:
Declare a global variable :
var totalCount : NSInteger?
var isGetResponse : Bool = true
var activityIndiator : UIActivityIndicatorView?
Set the 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:
self.totalCount = array.count
self.isGetResponse = true
Step 3:
Write this code :
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.
回答5:
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). 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.
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. It can be little bit complex so i can share a code block if you want. Good luck:)
回答6:
-- itemList - your data array.
-- pageCount - variable used to keep track of the number of pages.
-- totalCount - total number of data
--- append data to itemList every time you call the API.
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if indexPath.row == itemList.count - 1 && itemList.count < totalCount{
pageCount += 1
// Call API here
}
}
回答7:
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
func YourApi(page1: Int) {
let mypage = String(page1)
let request: String = String.init(format:"apiName/%@", mypage)
print(request)
}
That's it.
回答8:
The code in willDisplay cell
method calls load more function while your scroll is 5 cells away from the end. 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 { }
}