【发布时间】:2011-03-20 14:12:44
【问题描述】:
有什么方法可以知道当前表格视图单元格是否可见? 我有一个表格视图,其第一个单元格(0)是一个 uisearchbar。 如果搜索未激活,则通过偏移隐藏单元格 0。 当表格只有几行时,第 0 行可见。 如何判断第0行是可见还是顶行?
【问题讨论】:
标签: iphone uitableview
有什么方法可以知道当前表格视图单元格是否可见? 我有一个表格视图,其第一个单元格(0)是一个 uisearchbar。 如果搜索未激活,则通过偏移隐藏单元格 0。 当表格只有几行时,第 0 行可见。 如何判断第0行是可见还是顶行?
【问题讨论】:
标签: iphone uitableview
UITableView 有一个名为indexPathsForVisibleRows 的实例方法,它将为表中当前可见的每一行返回NSArray 的NSIndexPath 对象。您可以使用所需的任何频率检查此方法并检查正确的行。例如,如果tableView 是对您的表的引用,则以下方法会告诉您第 0 行是否在屏幕上:
-(BOOL)isRowZeroVisible {
NSArray *indexes = [tableView indexPathsForVisibleRows];
for (NSIndexPath *index in indexes) {
if (index.row == 0) {
return YES;
}
}
return NO;
}
因为UITableView 方法返回NSIndexPath,您可以轻松扩展它以查找部分或行/部分组合。
这比visibleCells 方法对您更有用,后者返回一个表格单元对象数组。表格单元格对象会被回收,因此在大型表格中,它们最终不会与您的数据源建立简单的关联。
【讨论】:
for 语句循环遍历数组中的所有索引,如果您要查找第0节的索引0的行,直接写@可能更容易987654331@
检查tableview单元格是否可见或不使用此行代码
if(![tableView.indexPathsForVisibleRows containsObject:newIndexPath])
{
// your code
}
这里newIndexPath是检查单元格的IndexPath.....
Swift 3.0
if !(tableView.indexPathsForVisibleRows?.contains(newIndexPath)) {
// Your code here
}
【讨论】:
我在 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 }
} }
【讨论】:
Swift 版本:
if let indices = tableView.indexPathsForVisibleRows {
for index in indices {
if index.row == 0 {
return true
}
}
}
return false
【讨论】:
另一种解决方案(也可用于检查一行是否完全可见)是检查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
}
【讨论】:
请注意,“有点可见”是“可见”。此外,在 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
}
【讨论】:
斯威夫特:
改进的@Emil 答案
extension UITableView {
func isCellVisible(indexPath: IndexPath) -> Bool {
guard let indexes = self.indexPathsForVisibleRows else {
return false
}
return indexes.contains(indexPath)
}
}
【讨论】:
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)
{
【讨论】:
最好按帧检查
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
}
【讨论】: