如何检索所有可见的表节标题视图

有没有办法让所有的节标题视图是可见的?

类似于UITableView的visibleCells实例方法

使用indexPathsForVisibleRows的问题是它不包含没有任何行的部分。 要获得所有可见部分,包括空白部分,您必须检查部分的矩形并将其与表的contentOffset进行比较。

您还必须注意平面样式与浮动部分之间的区别以及不带浮动部分的分组样式。

我做了一个支持这个计算的类别:

@interface UITableView (VisibleSections) // Returns an array of NSNumbers of the current visible section indexes - (NSArray *)indexesOfVisibleSections; // Returns an array of UITableViewHeaderFooterView objects of the current visible section headers - (NSArray *)visibleSections; @end @implementation UITableView (VisibleSections) - (NSArray *)indexesOfVisibleSections { // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. NSMutableArray *visibleSectionIndexes = [NSMutableArray arrayWithCapacity:self.numberOfSections]; for (int i = 0; i < self.numberOfSections; i++) { CGRect headerRect; // In plain style, the section headers are floating on the top, so the section header is visible if any part of the section's rect is still visible. // In grouped style, the section headers are not floating, so the section header is only visible if it's actualy rect is visible. if (self.style == UITableViewStylePlain) { headerRect = [self rectForSection:i]; } else { headerRect = [self rectForHeaderInSection:i]; } // The "visible part" of the tableView is based on the content offset and the tableView's size. CGRect visiblePartOfTableView = CGRectMake(self.contentOffset.x, self.contentOffset.y, self.bounds.size.width, self.bounds.size.height); if (CGRectIntersectsRect(visiblePartOfTableView, headerRect)) { [visibleSectionIndexes addObject:@(i)]; } } return visibleSectionIndexes; } - (NSArray *)visibleSections { NSMutableArray *visibleSects = [NSMutableArray arrayWithCapacity:self.numberOfSections]; for (NSNumber *sectionIndex in self.indexesOfVisibleSections) { UITableViewHeaderFooterView *sectionHeader = [self headerViewForSection:sectionIndex.intValue]; [visibleSects addObject:sectionHeader]; } return visibleSects; } @end 

我真的很喜欢@ adamsiton的解决scheme,我最终翻译成swift。 这是FYI。

我调用了文件UITableView + VisibleSections.swift

 import UIKit public extension UITableView { var indexesOfVisibleSections: [Int] { // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. var visibleSectionIndexes = [Int]() for i in 0..<numberOfSections { var headerRect: CGRect? // In plain style, the section headers are floating on the top, so the section header is visible if any part of the section's rect is still visible. // In grouped style, the section headers are not floating, so the section header is only visible if it's actualy rect is visible. if (self.style == .plain) { headerRect = rect(forSection: i) } else { headerRect = rectForHeader(inSection: i) } if headerRect != nil { // The "visible part" of the tableView is based on the content offset and the tableView's size. let visiblePartOfTableView: CGRect = CGRect(x: contentOffset.x, y: contentOffset.y, width: bounds.size.width, height: bounds.size.height) if (visiblePartOfTableView.intersects(headerRect!)) { visibleSectionIndexes.append(i) } } } return visibleSectionIndexes } var visibleSectionHeaders: [UITableViewHeaderFooterView] { var visibleSects = [UITableViewHeaderFooterView]() for sectionIndex in indexesOfVisibleSections { if let sectionHeader = headerView(forSection: sectionIndex) { visibleSects.append(sectionHeader) } } return visibleSects } } 

对于普通样式表,您可以获取可见的行。 从这些,得到一组可见的部分。 从这里,从表格中获取节标题视图。

 NSArray *visibleRows = [self.tableView indexPathsForVisibleRows]; NSMutableIndexSet *sections = [[NSMutableIndexSet alloc] init]; for (NSIndexPath *indexPath in visibleRows) { [sections addIndex:indexPath.section]; } NSMutableArray *headerViews = [NSMutableArray array]; [sections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { UIView *view = [self.tableView headerViewForSection:idx]; [headerViews addObject:view]; }]; 

注意:未经testing的代码可能包含拼写错误。 这对分组样式表不起作用。

本杰明·惠勒的解决scheme是一个伟大的Swift解决scheme。 我修复了一个问题,因为新的Swift语法,并修改它以匹配由默认的UITableView实现提供的.visibleCells属性。

 extension UITableView { /// The table section headers that are visible in the table view. (read-only) /// /// The value of this property is an array containing UITableViewHeaderFooterView objects, each representing a visible cell in the table view. /// /// Derived From: [http://stackoverflow.com/a/31029960/5191100](http://stackoverflow.com/a/31029960/5191100) var visibleSectionHeaders: [UITableViewHeaderFooterView] { get { var visibleSects = [UITableViewHeaderFooterView]() for sectionIndex in indexesOfVisibleSections() { if let sectionHeader = self.headerViewForSection(sectionIndex) { visibleSects.append(sectionHeader) } } return visibleSects } } private func indexesOfVisibleSections() -> Array<Int> { // Note: We can't just use indexPathsForVisibleRows, since it won't return index paths for empty sections. var visibleSectionIndexes = Array<Int>() for (var i = 0; i < self.numberOfSections; i++) { var headerRect: CGRect? // In plain style, the section headers are floating on the top, // so the section header is visible if any part of the section's rect is still visible. // In grouped style, the section headers are not floating, // so the section header is only visible if it's actual rect is visible. if (self.style == .Plain) { headerRect = self.rectForSection(i) } else { headerRect = self.rectForHeaderInSection(i) } if headerRect != nil { // The "visible part" of the tableView is based on the content offset and the tableView's size. let visiblePartOfTableView: CGRect = CGRect( x: self.contentOffset.x, y: self.contentOffset.y, width: self.bounds.size.width, height: self.bounds.size.height ) if (visiblePartOfTableView.intersects(headerRect!)) { visibleSectionIndexes.append(i) } } } return visibleSectionIndexes } } 

在这种情况下,我想你设置cell.tagcellForRowAtIndexPath的当前部分( indexPath.section ),并使用visibleCells方法,如你所描述的和headerViewForSection

要获取当前可见的部分,你可以通过检查当前可见的单元格的indexpath部分来获取它,所以这个函数可以返回到可见部分

 - (NSArray *)indexesOfVisibleSections { NSMutableArray *visibleSections = [NSMutableArray array]; for (UITableViewCell * cell in [self.tableView visibleCells]) { if (![visibleSections containsObject:[NSNumber numberWithInteger:[self.tableView indexPathForCell:cell].section]]) { [visibleSections addObject:[NSNumber numberWithInteger:[self.tableView indexPathForCell:cell].section]]; } } return visibleSections; } 

而要访问节视图,你可以使用

 - (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section; 

快速浏览一下UITableView文档给我们提供了indexPathsForVisibleRows ,并将它与map结合起来就是我们需要的数组:

 tableView.indexPathsForVisibleRows.map{ tableView.headerView(forSection: $0.section) } 

map将返回我们可见的标题段的数组。