检测UITableView节标题是否浮动

时间:2012-06-26 14:12:10

标签: ios uitableview

有没有办法检测UITableView中某个部分的标题当前是否正在浮动?我想将表格视图滚动到标题位置,只有它是浮动的。

提前致谢!

6 个答案:

答案 0 :(得分:8)

如果该部分的第一个单元格不再可见,则标题将浮动。所以:

NSIndexPath *topCellPath = [[self.tableView indexPathsForVisibleRows] objectAtIndex:0];
if (topCellPath.row != 0)
{
    // Header must be floating!
}

通过使用scrollToRowAtIndexPath:atScrollPosition:animated:滚动到索引路径并且滚动位置为UITableViewScrollPositionNone,您可以实现类似的效果 - 如果该部分中的第一个单元格已经在屏幕上,则不会滚动。

答案 1 :(得分:1)

您可以先存储章节标题视图的原始矩形。

 headerView.originalPoint = [tableView rectForHeaderInSection:section].origin;

scrollViewDidScroll:scrollView消息发送到标题。

在标题视图中

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
   BOOL isFloating = self.frame.origin.y > self.originalPoint.y;
   if (isFloating) {
       //DO what you want
   }
}

答案 2 :(得分:1)

这很有效。

@implementation UITableView (rrn_extensions)

-(BOOL)rrn_isFloatingSectionHeaderView:(UITableViewHeaderFooterView *)view {
    NSNumber *section = [self rrn_sectionForHeaderFooterView:view];
    return [self rrn_isFloatingHeaderInSection:section.integerValue];
}

-(BOOL)rrn_isFloatingHeaderInSection:(NSInteger)section {
    CGRect frame = [self rectForHeaderInSection:section];
    CGFloat y = self.contentInset.top + self.contentOffset.y;
    return y > frame.origin.y;
}

-(NSNumber *)rrn_sectionForHeaderFooterView:(UITableViewHeaderFooterView *)view {
    for (NSInteger i = 0; i < [self numberOfSections]; i++) {
        CGPoint a = [self convertPoint:CGPointZero fromView:[self headerViewForSection:i]];
        CGPoint b = [self convertPoint:CGPointZero fromView:view];
        if (a.y == b.y) {
            return @(i);
        }
    }
    return nil;
}

@end

答案 3 :(得分:1)

适用于UITableViewsUICollectionViews的iOS 11.0+解决方案

在两种情况下,都使用scrollViewDidScroll方法。您可以使用currentHeader属性存储显示在顶部的当前标题。 HEIGHT_OF_HEADER_VIEW是您应该指定自己的值。

对于UITableView

private var currentHeader: UITableViewHeaderFooterView? {
    willSet {
        // Handle `old` header
    } didSet {
        // Hanlde `new` header
    }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let point = CGPoint(x: 0, y: HEIGHT_OF_HEADER_VIEW + tableView.contentOffset.y + tableView.adjustedContentInset.top)
    guard let path = tableView.indexPathForRow(at: point) else {
        return
    }

    let section = path.section
    let rect = tableView.rectForHeader(inSection: section)
    let converted = tableView.convert(rect, to: tableView.superview)
    let safeAreaInset = tableView.safeAreaInsets.top

    // Adding 1 offset because of large titles that sometimes cause slighly wrong converted values
    guard converted.origin.y <= safeAreaInset,
        let header = tableView.headerView(forSection: section) else {
        return
    }
    currentHeader = header
}

对于UICollectionView

private var currentHeader: UICollectionReusableView? {
    willSet {
        // Handle `old` header
    } didSet {
        // Handle `new` header
    }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let x = (collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.sectionInset.left ?? 0
    let point = CGPoint(x: x, y: HEIGHT_OF_HEADER_VIEW + collectionView.contentOffset.y + collectionView.adjustedContentInset.top)

    guard let path = collectionView.indexPathForItem(at: point),
        let rect = collectionView.layoutAttributesForSupplementaryElement(ofKind: UICollectionView.elementKindSectionHeader, at: IndexPath(row: 0, section: path.section))?.frame else {
        return
    }

    let converted = collectionView.convert(rect, to: collectionView.superview)
    let safeAreaInset = collectionView.safeAreaInsets.top

    guard converted.origin.y <= safeAreaInset,
        let header = collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: IndexPath(row: 0, section: path.section)) else {
        return
    }
    currentHeader = header
}

答案 4 :(得分:0)

该代码适用于我。

- (BOOL)isSection0HeaderSticky {
    CGRect originalFrame = [self.listTableView rectForHeaderInSection:0];

    UIView *section0 = [self.listTableView headerViewForSection:0];

    if (originalFrame.origin.y < section0.frame.origin.y) {
        return  YES;
    }
    return NO;
}

答案 5 :(得分:0)

添加@ robdashnash答案的快速端口

extension UITableView
{
     func isFloatingSectionHeader( view:UITableViewHeaderFooterView )->Bool
     {
          if let section = section( for:view )
          {
              return isFloatingHeaderInSection( section:section )
          }
          return false
      }

     func isFloatingHeaderInSection( section:Int )->Bool
     {
         let frame = rectForHeader( inSection:section )
         let y = contentInset.top + contentOffset.y
         return y > frame.origin.y
     }

     func section( for view:UITableViewHeaderFooterView )->Int?
     {
         for i in stride( from:0, to:numberOfSections, by:1 )
         {
             let a = convert( CGPoint.zero, from:headerView( forSection:i ) )
             let b = convert( CGPoint.zero, from:view )
             if a.y == b.y
             {
                 return i
             }
         }
         return nil
     }
 }