簡體   English   中英

UITableView - 在viewDidAppear之前滾動到底部

[英]UITableView - Scroll to bottom before viewDidAppear

如果標題不明顯,我想要的應該是簡單的,因為當用戶第一次看到它時( 在他看到它之前,沒有動畫 tableView開始一直滾動到底部。

所以,我知道這已經得到了幾次回答,但這些解決方案似乎都沒有發揮作用。 為了給出一些上下文,我現在使用的是Swift,autolayout和最新版本的iOS。

約束

我需要支持一些事情:

  1. 在用戶看到它之前加載它(顯然沒有動畫)。
  2. 動態單元格高度,即它們的高度由UILabel(如消息傳遞應用程序 - 在故事板中使用自動布局)確定。
  3. 我的UITableView位於UIScrollViewUIScrollView水平滾動, UITableView垂直滾動)。
  4. UITableView位於childViewController ,即我將它添加到主UIViewController (由於某種原因,使得viewWillAppear不被調用 - 仍然調用viewDidAppear )。

我將總結一下我的嘗試:

至於實施:

  1. tableView.contentOffset = CGPoint(x: 0, y: CGFloat.max

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

至於我試圖調用這些實現的地方:

  1. viewDidLoad
  2. viewWillAppear
  3. viewDidLayoutSubviews (僅在第一次調用時,我使用屬性來跟蹤它)
  4. viewDidAppear (即使這不會給我我想要的)
  5. 在我的模型的didSet

在那之前我總是調用tableView.reloadData

我不想做的事:

tableView.transform = CGAffineTransformMakeScale(1, -1)

+

cell.transform = CGAffineTransformMakeScale(1, -1)

(我假設如果你想建議這個解決方案,那是因為你知道我正在談論的黑客。如果你不這樣做,那么你就不會建議這樣做,所以你不需要了解如何有用)

我不想要這個的原因之一是因為現在我無法滾動到頂部...

我注意到的問題:

  1. tableViewcontentSize (作為UIScrollView子類)在它出現后第一次滾動時會發生變化。 是的,我的意思是contentSize ,而不是contentOffset ,滾動時它會多次更改。 滾動瀏覽整個tableView一次后,它不再發生變化。
  2. 有些人說它適用於較少的細胞(說實話,它在某些時候對我有用),所以試試至少20項。
  3. viewWillAppear不會被調用,但viewDidAppear會調用。

我非常感謝任何解決方案(除了我提到的我不想要的解決方案)。 即使是hacky,只要他們不打破其他東西。

正如旁注, scrollToRowAtIndexPath...不會縮放,例如,如果你有2000個項目它太慢了。 所以理想情況下我更喜歡可擴展的解決方案。

回答后的編輯:

  1. 在@ 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中你需要的。

  1. 取消選中“自動”tableview的屬性; 行高和估計

在此輸入圖像描述

  1. 添加此代碼

     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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM