[英]swift ios add infinite scroll pagination to uitableview
我想知道 tableview 是否有任何內置的 function 來添加無限滾動/分頁。
現在我的 VC 看起來像這樣:
var data: JSON! = []
override func viewDidLoad() {
super.viewDidLoad()
//Init start height of cell
self.tableView.estimatedRowHeight = 122
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.delegate = self
self.tableView.dataSource = self
savedLoader.startAnimation()
//Load first page
loadSaved(1)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("aCell") as! SavedTableViewCell
let info = data[indexPath.row]
cell.configureWithData(info)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("WebSegue", sender: indexPath)
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
我通過為 function 提供我要加載的當前頁面來使用loadSaved(1)獲取我的數據。 function 使用 alomofire 發出 API 請求,然后填充var 數據:JSON! = []包含應顯示的數據
所以我想做的是當我滾動到 tableview 的底部時應該調用loadSaved(2)將更多數據加載到 tableview
UITableViewDelegate 有一個 tableView (_: will Display: for Row At: ) 實例方法,它“告訴委托 table view 即將為特定行繪制一個單元格。”
在你的情況下,我會像這樣使用它:
override open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if indexPath.row == data.count-1 { //you might decide to load sooner than -1 I guess...
//load more into data here
}
}
根據您的代碼,您可能需要對此進行一些檢查,以確保在您加載了所有數據后不會陷入無限循環......
不, UITableView
沒有任何內置函數來實現無限滾動或按需加載單元格。 您可以使用的是UIScrollViewDelegate
的函數scrollViewDidScroll(_:)
在UITableView
默認實現,這樣就知道用戶何時滾動超過UITableView
定義的原始高度。
例如像在這段代碼中:
var indexOfPageToRequest = 1
override func scrollViewDidScroll(scrollView: UIScrollView) {
// calculates where the user is in the y-axis
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height {
// increments the number of the page to request
indexOfPageToRequest += 1
// call your API for more data
loadSaved(indexOfPageToRequest)
// tell the table view to reload with the new data
self.tableView.reloadData()
}
}
為了實現在結尾處添加元素的其余部分的結果UITableView
你應該添加新的元素到數據源,在你的情況下data
的函數中loadSaved(numberOfPage)
我希望這對你有幫助。
以上所有答案都是正確的,但對於 iOS 10 及更高版本,我們有一個非常好的
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])
這是一個需要設置的預取委托
tableView.prefetchDataSource = self
RayWeinderlich有一個關於這個主題的不錯的教程。 由於 Rays 是一個可靠的網站,我不會在這里發布代碼
我修改了維克多的答案並將其用作,
var indexOfPageRequest = 1
var loadingStatus = false
func loadData(){
if !loadingStatus{
loadingStatus = true
viewModel.getData(pageIndex: indexOfPageRequest)
}
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
// calculates where the user is in the y-axis
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height {
// increments the number of the page to request
indexOfPageRequest += 1
// call your API for more data
loadData()
// tell the table view to reload with the new data
self.tableView.reloadData()
}
}
接收數據時將 loadingStatus 重置為 true。 沒有檢查視圖是否已經加載了更多數據,tableview 正在閃爍。
首先,創建一個帶有Xib
文件的UITableViewCell
並在單元格的中心添加一個UIActivityIndicatorView
。
然后, Control+left click
並將UIActivityIndicatorView
拖到您的 .swift 文件中,並命名為activityIndicator
……並添加“ loadingcellid
”作為Identifier
。
現在,讓我們進入我們有UITableView
TableViewController
,並在viewDidLoad()
注冊加載單元。
override func viewDidLoad() {
super.viewDidLoad()
//...
//Register Loading Cell
let tableViewLoadingCellNib = UINib(nibName: "LoadingCell", bundle: nil)
self.tableView.register(tableViewLoadingCellNib, forCellReuseIdentifier: "tableviewloadingcellid")
}
在UITableView's
委托和數據源中,我們在numberOfRowsInSection
方法中添加以下代碼。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
//Return the amount of items
return itemsArray.count
} else if section == 1 {
//Return the Loading cell
return 1
} else {
//Return nothing
return 0
}
}
..我們返回 2 個部分(一個用於項目,一個用於Loading Cell
)。
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
在cellForRowAt
方法中,我們返回每個部分的單元格:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewitemcellid", for: indexPath) as! TableViewItemCell
cell.itemLabel.text = itemsArray[indexPath.row]
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier:
"tableviewloadingcellid", for: indexPath) as! TableViewLoadingCell
cell.activityIndicator.startAnimating()
return cell
}
}
...我們還設置了行height
。
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return 44 //Item Cell height
} else {
return 55 //Loading Cell height
}
}
接下來,我們使用方法scrollViewDidScroll
,來自UITableView
嵌入的UIScrollView
,來檢測用戶何時接近列表末尾以調用該方法......
var isLoading = false
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if (offsetY > contentHeight - scrollView.frame.height * 4) && !isLoading {
loadMoreData()
}
}
... loadMoreData() 下載更多數據。
func loadMoreData() {
if !self.isLoading {
self.isLoading = true
DispatchQueue.global().async {
// Fake background loading task for 2 seconds
sleep(2)
// Download more data here
DispatchQueue.main.async {
self.tableView.reloadData()
self.isLoading = false
}
}
}
}
它運行良好,形成更多:- https://johncodeos.com/how-to-add-load-more-infinite-scrolling-in-ios-using-swift/
拉維的回答看起來不錯。 但正如他最后指出的那樣,如果您使用scrollViewDidScroll(_ scrollView: UIScrollView)
,tableView 會閃爍很多
這是因為您每次滾動 tableView 時都試圖重新加載 tableView。
相反,您可以使用scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool)
委托方法來確定您是否已經足夠滾動並幾乎到達 tableView 的末尾。
override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height {
indexOfPageRequest += 1
loadData()
self.tableView.reloadData()
}
}
上面的 Ans 也是對的,但也可能有人幫助解決此代碼。
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath){
if(indexPath.row == self.arryOfData.count-1){
if(self.pageNumber <= self.resPgNumber){
if(remaining != 0){
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
spinner.startAnimating()
tableView.tableFooterView = spinner
tableView.tableFooterView?.isHidden = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.flgActivity = false
self.getActiveOrdersList()
}
}
else{
tableView.tableFooterView?.removeFromSuperview()
let view = UIView()
view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
tableView.tableFooterView = view
tableView.tableFooterView?.isHidden = true
}
}
else{
tableView.tableFooterView?.removeFromSuperview()
let view = UIView()
view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
tableView.tableFooterView = view
tableView.tableFooterView?.isHidden = true
}
}
else{
tableView.tableFooterView?.removeFromSuperview()
let view = UIView()
view.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(5))
tableView.tableFooterView = view
tableView.tableFooterView?.isHidden = true
}
}
我們有很多方法可以做到這一點。 所有不同方式的本質是當用戶滾動到最后一組時加載下一組數據。 我通過在 tableView 的末尾添加一個額外的特殊單元格來實現它,當該單元willDisplay cell: forRowAtIndexPath:
載到willDisplay cell: forRowAtIndexPath:
觸發下一組數據獲取。
雖然這很容易實現,但在較大的應用程序中,有時我們需要在很多地方實現它。 為了避免這種情況,我編寫了一個非侵入性且易於集成的小框架。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.