![](/img/trans.png)
[英]How to scroll to the bottom of a UITableView on the iPhone before the view appears
[英]UITableView - Scroll to bottom before viewDidAppear
如果標題不明顯,我想要的應該是簡單的,因為當用戶第一次看到它時( 在他看到它之前,沒有動畫 ) , tableView
開始一直滾動到底部。
所以,我知道這已經得到了幾次回答,但這些解決方案似乎都沒有發揮作用。 為了給出一些上下文,我現在使用的是Swift,autolayout和最新版本的iOS。
約束
我需要支持一些事情:
UITableView
位於UIScrollView
( UIScrollView
水平滾動, UITableView
垂直滾動)。 UITableView
位於childViewController
,即我將它添加到主UIViewController
(由於某種原因,使得viewWillAppear
不被調用 - 仍然調用viewDidAppear
)。 我將總結一下我的嘗試:
至於實施:
tableView.contentOffset = CGPoint(x: 0, y: CGFloat.max
tableView.scrollToRowAtIndexPath(indexPathForLastItem, atScrollPosition: .Bottom, animated: false)
var contentOffset = tableView.contentOffset
contentOffset.y = tableView.contentSize.height - tableView.bounds.size.height
tableView.setContentOffset(contentOffset, animated: false)
dispatch_async(dispatch_get_main_queue(), {
// tried option 1., 2. and 3. here
})
至於我試圖調用這些實現的地方:
viewDidLoad
viewWillAppear
viewDidLayoutSubviews
(僅在第一次調用時,我使用屬性來跟蹤它) viewDidAppear
(即使這不會給我我想要的) didSet
在那之前我總是調用tableView.reloadData
我不想做的事:
tableView.transform = CGAffineTransformMakeScale(1, -1)
+
cell.transform = CGAffineTransformMakeScale(1, -1)
(我假設如果你想建議這個解決方案,那是因為你知道我正在談論的黑客。如果你不這樣做,那么你就不會建議這樣做,所以你不需要了解如何有用)
我不想要這個的原因之一是因為現在我無法滾動到頂部...
我注意到的問題:
tableView
的contentSize
(作為UIScrollView
子類)在它出現后第一次滾動時會發生變化。 是的,我的意思是contentSize
,而不是contentOffset
,滾動時它會多次更改。 滾動瀏覽整個tableView
一次后,它不再發生變化。 viewWillAppear
不會被調用,但viewDidAppear
會調用。 我非常感謝任何解決方案(除了我提到的我不想要的解決方案)。 即使是hacky,只要他們不打破其他東西。
正如旁注, scrollToRowAtIndexPath...
不會縮放,例如,如果你有2000個項目它太慢了。 所以理想情況下我更喜歡可擴展的解決方案。
回答后的編輯:
在@ bsmith11的回答之后我嘗試了:
private var called = false override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if !called { dispatch_async(dispatch_get_main_queue(), { self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.bounds.height), animated: false) }) called = true } }
它沒有用。
在viewDidLayoutSubviews()
,將.contentOffset
設置為tableView.bounds.height
。 您需要在異步塊中啟動它以使tableView
時間加載它的內容。
dispatch_async(dispatch_get_main_queue()) { self.tableView.setContentOffset(tableView.bounds.height, animated: false) }
viewDidLayoutSubviews()
可以多次調用,因此您可能希望確保上面的代碼只被調用一次。
剛試過下面的代碼就行了。
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(true)
myArray = [["Data": "1234567890", "Height": 44],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "12345678901234567890", "Height": 88],["Data": "End of Table", "Height": 132]]
let no = myArray.count-1
let lastIndex = NSIndexPath(forRow: no, inSection: 0)
table1.scrollToRowAtIndexPath(lastIndex, atScrollPosition: .Bottom, animated: true)
}
將以下方法添加到自定義子類。
- (void)tableViewScrollToBottomAnimated:(BOOL)animated {
NSInteger numberOfRows = [_tableView numberOfRowsInSection:0];
if (numberOfRows) {
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}
}
在viewDidAppear
結束時調用[self tableViewScrollToBottomAnimated:NO]
可以正常工作。 一個問題是不幸的是,它還導致tableView:heightForRowAtIndexPath:
為每個單元tableView:heightForRowAtIndexPath:
三次。
我有完全相同的問題,在嘗試了所有東西(和你一樣)后,這個工作,關鍵是如果你使用autolayout,你必須在viewDidLayoutSubviews中編寫scrollToBottom代碼
將scrollToBottom初始化為true,然后執行此操作
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// Scroll table view to the last row
[self scrollToBottom];
}
-(void)scrollToBottom {
if (shouldScrollToLastRow)
{
CGPoint bottomOffset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height);
[self.tableView setContentOffset:bottomOffset animated:NO];
} }
這樣做可以確保你幾乎位於tableView的底部,但可能不會處於最底層,因為當你位於tableView的頂部時,不可能知道確切的底部偏移,所以之后我們可以實現scrollViewDidScroll
-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
float scrollViewHeight = scrollView.frame.size.height;
float scrollContentSizeHeight = scrollView.contentSize.height;
float scrollOffset = scrollView.contentOffset.y;
// if you're not at bottom then scroll to bottom
if (!(scrollOffset + scrollViewHeight == scrollContentSizeHeight))
{
[self scrollToBottom];
} else {
// bottom reached now stop scrolling
shouldScrollToLastRow = false;
}
}
private var called = false
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if !called {
dispatch_async(dispatch_get_main_queue(), {
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.bounds.height), animated: false)
})
called = true
}
}
我用我的UIScrollView嘗試了這段代碼。 它有效 。 如果我刪除了dispatch_async
它將無法正常工作。
Swift 3代碼
private var called = false
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if !called {
DispatchQueue.main.async(execute: {
self.tableView.setContentOffset(CGPoint(x: 0, y: self.tableView.bounds.height), animated: false)})
called = true
}
}
我認為調用[table setContentOffset:CGPointMake(0, CGFLOAT_MAX)]
和table.estimatedRowHeight = 50(change your value);
在ViewDidLoad中你需要的。
添加此代碼
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if scrollToBottomOnce == false { scrollToBottomOnce = true if self.items.count > 0 { self.tableView.setContentOffset(CGPoint(x: 0, y: CGFloat.greatestFiniteMagnitude), animated: false) } } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.