2010-07-24 109 views
48

有什麼方法可以知道桌面單元當前是否可見? 我有一個tableview的第一個單元格(0)是一個uisearchbar。 如果搜索未激活,則通過偏移量隱藏單元格0。 當表格只有幾行時,行0是可見的。 如何確定行0是可見的還是最上面一行?確定桌面單元是否可見

回答

93

UITableView有一個名爲indexPathsForVisibleRows的實例方法,該方法將爲當前可見的表中的每一行返回NSArrayNSIndexPath對象。你可以用你需要的任何頻率檢查這個方法,並檢查正確的行。例如,如果tableView是你的表的引用,以下方法會告訴你是否行0出現在屏幕上:

-(BOOL)isRowZeroVisible { 
    NSArray *indexes = [tableView indexPathsForVisibleRows]; 
    for (NSIndexPath *index in indexes) { 
    if (index.row == 0) { 
     return YES; 
    } 
    } 

    return NO; 
} 

因爲UITableView方法返回NSIndexPath,你可以很容易地擴展這個到查找部分或行/部分組合。

這比你的visibleCells方法更有用,它返回一個表格單元格對象數組。表單元對象得到回收,所以在大表中,它們最終不會有簡單的關聯返回到數據源。

+0

謝謝!這是非常有用的,但它應該是「indexPathsForVisibleRows」而不是「indexPathsForvisibleRows」 – mklfarha 2011-03-18 00:10:16

+0

感謝這個answer.Star丟失。 「for(NSIndexPath *索引中的索引){」 – 2011-06-27 14:55:12

+4

@Devunwired我有一個後續問題。如果我想檢查一行是否完全可見,該怎麼辦?你的代碼是好的,除了它也返回YES,如果行只是部分可見。謝謝! – pixelfreak 2011-10-02 00:20:41

1

IOS 4:

NSArray *cellsVisible = [tableView indexPathsForVisibleRows]; 
NSUInteger idx = NSNotFound; 
idx = [cellsVisible indexOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) 
{ 
    return ([(NSIndexPath *)obj compare:indexPath] == NSOrderedSame); 
}]; 

if (idx == NSNotFound) 
{ 
35

要檢查的tableview細胞可見或不可見使用此代碼行的

if(![tableView.indexPathsForVisibleRows containsObject:newIndexPath]) 
    { 
     // your code 
    } 

這裏newIndexPath是檢查電池的IndexPath .....

Swift 3.0

if !(tableView.indexPathsForVisibleRows?.contains(newIndexPath)) { 
    // Your code here 

} 
+0

我收到了關於聊天的保留計數的回覆謝謝...我問同樣的問題在這裏http://stackoverflow.com/questions/12990128/what-is-ios-retain-do-at-backend但我得到負分.. :(也爲+1這.. – 2012-10-30 09:10:28

4

另一種解決方案(也可用於檢查行是否完全可見)將檢查row的框架是否在tableview的可見區域內。

在下面的代碼,ip表示NSIndexPath

CGRect cellFrame = [tableView rectForRowAtIndexPath:ip]; 
if (cellFrame.origin.y<tableView.contentOffset.y) { // the row is above visible rect 
    [tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; 
} 
else if(cellFrame.origin.y+cellFrame.size.height>tableView.contentOffset.y+tableView.frame.size.height-tableView.contentInset.top-tableView.contentInset.bottom){ // the row is below visible rect 
    [tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:NO]; 
} 

而且使用cellForRowAtIndexPath:應該工作,因爲它返回一個nil對象,如果該行不可見:

if([tableView cellForRowAtIndexPath:ip]==nil){ 
    // row is not visible 
} 
4

斯威夫特版本:

if let indices = tableView.indexPathsForVisibleRows { 
    for index in indices { 
     if index.row == 0 { 
      return true 
     } 
    } 
} 
return false 
7

我用這在Swift 3.0

extension UITableView { 

    /// Check if cell at the specific section and row is visible 
    /// - Parameters: 
    /// - section: an Int reprenseting a UITableView section 
    /// - row: and Int representing a UITableView row 
    /// - Returns: True if cell at section and row is visible, False otherwise 
    func isCellVisible(section:Int, row: Int) -> Bool { 
     guard let indexes = self.indexPathsForVisibleRows else { 
      return false 
     } 
     return indexes.contains {$0.section == section && $0.row == row } 
    } } 
+0

奇妙的東西! – Fattie 2017-02-18 19:29:02

0

請注意,「有點可見」是「可見的」。此外,在viewWillAppear中,當佈局正在進行時,您可能會從indexPathsForVisibleRows獲得誤報,如果您正在查看最後一行,即使調用layoutIfNeeded()也無法幫助您處理表格。您需要在viewDidAppear之後檢查內容。

如果最後一行是完全可見的,則此swift 3.1代碼將禁用滾動。在viewDidAppear之後調用它。

let numRows = tableView.numberOfRows(inSection: 0) // this can't be in viewWillAppear because the table's frame isn't set to proper height even after layoutIfNeeded() 
    let lastRowRect = tableView.rectForRow(at: IndexPath.init(row: numRows-1, section: 0)) 
    if lastRowRect.origin.y + lastRowRect.size.height > tableView.frame.size.height { 
     tableView.isScrollEnabled = true 
    } else { 
     tableView.isScrollEnabled = false 
    }