【问题标题】:Determine if a tableview cell is visible确定表格视图单元格是否可见
【发布时间】:2011-03-20 14:12:44
【问题描述】:

有什么方法可以知道当前表格视图单元格是否可见? 我有一个表格视图,其第一个单元格(0)是一个 uisearchbar。 如果搜索未激活,则通过偏移隐藏单元格 0。 当表格只有几行时,第 0 行可见。 如何判断第0行是可见还是顶行?

【问题讨论】:

标签: iphone uitableview


【解决方案1】:

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 方法对您更有用,后者返回一个表格单元对象数组。表格单元格对象会被回收,因此在大型表格中,它们最终不会与您的数据源建立简单的关联。

【讨论】:

  • 谢谢!这很有帮助,但应该是“indexPathsForVisibleRows”而不是“indexPathsForvisibleRows”
  • @Devunwired 我有一个后续问题。如果我想检查一行是否完全可见怎么办。您的代码很好,但如果该行仅部分可见,它也会返回 YES。谢谢!
  • 请注意,不要使用for 语句循环遍历数组中的所有索引,如果您要查找第0节的索引0的行,直接写@可能更容易987654331@
  • 参考@AliSoftware 的评论,现在应该说 indexPathForRow
  • @mkc842 那么检查单元格是否完全可见的正确方法是什么?
【解决方案2】:

检查tableview单元格是否可见或不使用此行代码

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

这里newIndexPath是检查单元格的IndexPath.....

Swift 3.0

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

}

【讨论】:

  • 我收到了您关于聊天保留计数的回复,谢谢...我在这里问了同样的问题stackoverflow.com/questions/12990128/…,但我得到了负分..:(另外,为此 +1..跨度>
  • 您必须先在 swift 中打开可选的包装。
  • 总是返回 false
【解决方案3】:

我在 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 }
    }  }

【讨论】:

  • 这在整个单元格可见之前不起作用。如果单元格的一小部分(最小)部分不可见,这将返回 false
【解决方案4】:

Swift 版本:

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

【讨论】:

    【解决方案5】:

    另一种解决方案(也可用于检查一行是否完全可见)是检查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
    }
    

    【讨论】:

      【解决方案6】:

      请注意,“有点可见”是“可见”。此外,在 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
          }
      

      【讨论】:

        【解决方案7】:

        斯威夫特:

        改进的@Emil 答案

        extension UITableView {
            
            func isCellVisible(indexPath: IndexPath) -> Bool {
                guard let indexes = self.indexPathsForVisibleRows else {
                    return false
                }
                return indexes.contains(indexPath)
            }
        }
        

        【讨论】:

          【解决方案8】:

          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)
          {
          

          【讨论】:

            【解决方案9】:

            最好按帧检查

            let rectOfCellInSuperview = yourTblView.convert(yourCell.frame, to: yourTblView.superview!) //make sure your tableview has Superview
            if yourTblView.frame.contains(rectOfCellInSuperview) == false {
                   //Your cell is not visible
            }
            

            【讨论】:

              猜你喜欢
              • 2020-03-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-09-10
              • 2013-05-26
              相关资源
              最近更新 更多