【问题标题】:Change Default Scrolling Behavior of UITableView Section Header更改 UITableView 节标题的默认滚动行为
【发布时间】:2010-10-14 11:13:11
【问题描述】:

我有一个包含两个部分的 UITableView。这是一个简单的表格视图。我正在使用 viewForHeaderInSection 为这些标题创建自定义视图。到目前为止,一切顺利。

默认的滚动行为是,当遇到一个部分时,部分标题保持锚定在导航栏下方,直到下一个部分滚动到视图中。

我的问题是:我可以更改默认行为,以便节标题不会停留在顶部,而是在导航栏下方滚动其余部分行?

我是否遗漏了一些明显的东西?

谢谢。

【问题讨论】:

标签: ios iphone uitableview cocoa-touch


【解决方案1】:

如果是我这样做,我会利用 Plain 样式的 UITableViews 具有粘性标题而 Grouped 样式的 UITableViews 没有这一事实。我可能至少会尝试使用自定义表格单元格来模仿分组表格中普通单元格的外观。

我实际上没有尝试过,所以它可能不起作用,但我建议这样做。

【讨论】:

  • 应该可以,但是试过了吗?当@voidStern 的回答完美时,似乎需要做很多工作!
  • 当我有两个以上的部分时,voidStern 的答案对我不起作用。 Colin 的答案更简单/更优雅,无需手动移动节号和添加节数。
  • 提示:使用tableView.separatorColor = [UIColor clearColor]; 模拟一个普通的表格视图。
  • 我尝试这样做,但是当我无法使分组的表格单元格看起来像普通的单元格时,即删除单元格两侧的左右边距。你是怎么做到的?
  • 非常感谢你让 UITableViewStyle 变得清晰,即分组和简单,它决定了 tableview 的部分页眉/页脚是否会粘。非常感谢@Colin Barrett
【解决方案2】:

我将表格添加到滚动视图中,这似乎效果很好。

【讨论】:

    【解决方案3】:

    为您的 tableView 分配一个负插图。如果您有 22px 高的部分标题,并且您不希望它们变得粘稠,请在 reloadData 添加后立即添加:

    self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
    self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 
    

    对我来说就像一个魅力。也适用于部分页脚,只需在底部指定负插图即可。

    【讨论】:

    • 这只是砍掉第一个标题??
    • 完美地为我工作!!谢谢
    【解决方案4】:

    我解决这个问题的方法是根据UITableViewControllerDelegate(扩展UIScrollViewDelegate)中的contentInset调整contentOffset,如下:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
           CGFloat sectionHeaderHeight = 40;
       if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
           scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
       } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
           scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
       }
    }
    

    这里唯一的问题是它在滚动回到顶部时会失去一点反弹。


    {注意:“40”应该是您的第 0 节标题的确切高度。如果您使用大于第 0 节标题高度的数字,您会看到手指感觉受到影响(尝试像“1000”,您会看到弹跳行为在顶部有点奇怪)。如果数字与您的第 0 节标题高度匹配,则手指感觉似乎是完美或接近完美。}

    【讨论】:

    • 比上面的完美解决方案。
    • 谢谢!这是一个完美的解决方案。你有节页脚的解决方案吗?
    • 这个解决方案不能正确处理点击菜单栏,它应该滚动到列表的顶部。
    • 如果你需要节页脚视图的相同行为,只需像这样更改最后一行:scrollView.contentInset = UIEdgeInsetsMake(0, 0, sectionHeaderHeight, 0)
    • 这似乎足够了:scrollView.contentInset = UIEdgeInsetsMake(scrollView.contentOffset.y >= 0 ? -scrollView.contentOffset.y : 0, 0, 0, 0);
    【解决方案5】:

    您还可以在顶部添加一个零行的部分,只需将上一个部分的页脚用作下一个部分的页眉。

    【讨论】:

    • 在我有超过 2 个部分的情况下,页脚将锚定在底部..
    • 这很有创意,但如果您使用 NSFetchedResultsController 加载表格,则需要调整 indexPath。
    • +1 迄今为止最好的解决方案 - 花了我 3 行来实现!
    • 辉煌辉煌辉煌 :-)
    • 这对于锚定的页脚如何工作?将不胜感激一些帮助!谢谢
    【解决方案6】:

    需要做几件事来以一种非 hacky 的方式解决这个问题:

    1. 将表格视图样式设置为UITableViewStyleGrouped
    2. 将表视图backgroundColor 设置为[UIColor clearColor]
    3. 将每个表格视图单元格上的backgroundView 设置为带有backgroundColor [UIColor clearColor] 的空视图
    4. 如有必要,适当设置表格视图rowHeight,或者如果各个行的高度不同,则覆盖tableView:heightForRowAtIndexPath:

    【讨论】:

    • (+1) @Neil,我尝试了你的答案,但不幸的是,对于 UITableViewStyleGrouped,表格单元格有额外的边距,会改变它们与标题的对齐方式。当您实际上想要描绘一个多列表并使用标题来显示列标题(然后让各个表条目与这些标题对齐)时,这是一个问题。
    【解决方案7】:

    将表格的headerView设置为与剖面视图中的表头高度相同的透明视图。同时在 -height 处使用 y 框架初始化 tableview。

    self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];
    
    UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
    [self.tableView setTableHeaderView:headerView];
    

    【讨论】:

      【解决方案8】:

      我知道它来晚了,但我找到了最终的解决方案!

      如果您有 10 个部分,您想要做的是让 dataSource 返回 20。部分标题使用偶数,部分内容使用奇数。像这样的

      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
          if (section%2 == 0) {
              return 0;
          }else {
              return 5;
          }
      }
      
      -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
          if (section%2 == 0) {
              return [NSString stringWithFormat:@"%i", section+1];
          }else {
              return nil;
          }
      }
      

      瞧! :D

      【讨论】:

      • 好主意。但如果你有部分索引标题,我怀疑这会把它们弄乱。
      • 为什么?你可以对章节标题做同样的事情。只要记住奇数的 nil 和偶数的标题即可。
      • 是的 - 这种方法效果很好。这是很多簿记(可能与我获得章节标题的方式有关)但它有效。诀窍是 numberOfRowsInSection 和 cellForRowAtIndexPath 使用 if (section%2!=0 && section!=0) 而 titleForHeaderInSection 和其他部分索引函数使用 if (section%2==0)
      • 发起者应该选择这个作为答案。如果有一种方法可以将 uitableview 子类化以自动锚定部分标题,那就太好了。
      • 这对我来说效果最好。我首先尝试了@Colin 的解决方案,但它不适用于我正在使用的高度定制的UITableView
      【解决方案9】:

      我了解到只需设置 tableHeaderView 属性即可,即:

       tableView.tableHeaderView = customView;
      

      就是这样。

      【讨论】:

        【解决方案10】:

        我找到了另一种解决方案,使用每个部分的第一个单元格而不是真正的标题部分,这个解决方案看起来不太干净,但效果很好,您可以为标题部分使用定义的原型单元格,并且在cellForRowAtIndexPath 方法要求 indexPath.row==0,如果为真,则使用标题部分原型单元格,否则使用您的默认原型单元格。

        【讨论】:

        • 如果您仍想使用indexPath.rowindexPath.section,请确保为- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 返回高度为0.0f,以便您的标题不可见。
        【解决方案11】:

        检查我的答案here。这是实现非浮动节标题的最简单方法 没有任何黑客攻击。

        【讨论】:

          【解决方案12】:

          原贴Here,使用IB的快速解决方案。虽然很简单,但同样可以通过编程方式完成。

          实现这一点的一种可能更简单的方法(使用 IB):

          将 UIView 拖到您的 TableView 上,使其成为标题视图。

          1. 将标题视图高度设置为 100 像素
          2. 将tableview contentInset(顶部)设置为-100
          3. 部分标题现在将像任何常规单元格一样滚动。

          有人评论说这个解决方案隐藏了第一个标题,但我没有注意到任何此类问题。它对我来说非常有效,是迄今为止我见过的最简单的解决方案。

          【讨论】:

          • 请注意,您可能应该将视图设置为使用 clearcolor 的背景颜色,否则如果您滚动到顶部,您会看到反弹中的白色。
          • 它确实隐藏了我的第一个标题
          • Leena,你运行的是哪个版本的 iOS?视图是 UITableViewController,还是带有 UITableView 的 UIView?我不确定为什么对某些人来说这个解决方案隐藏了第一个标题,所以我试图找出任何差异。
          • 这个解决方案是完美的。我正在寻找无限的顶部和底部单元格背景外观 - 这完全可以实现。不错!
          • 这个解决方案非常好。比此线程中的其他答案更容易完成。在我看来,这应该是公认的答案。
          【解决方案13】:

          到目前为止,我对此处描述的解决方案并不满意,因此我尝试将它们结合起来。结果是以下代码,灵感来自@awulf 和@cescofry。它对我有用,因为我没有真正的表格视图标题。如果您已经有表格视图标题,则可能需要调整高度。

          // Set the edge inset
          self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);
          
          // Add a transparent UIView with the height of the section header (ARC enabled)
          [self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];
          

          【讨论】:

          • 这是我找到的最简单的解决方案。
          • 这在 iOS9.2 上对我有用,所以即使是较旧的答案,它仍然有效。它并没有隐藏第一节标题。工作,并且完美地工作。
          • 完美。如果您的 tableview 已经有一个标题,只需将其高度增加偏移量,然后增加标题内容的顶部约束常量以将内容向下移动到原始位置
          【解决方案14】:

          @LocoMike 的回答最适合我的 tableView,但是在使用页脚时它也坏了。 因此,这是使用页眉和页脚时的更正解决方案:

          - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
          {
              return (self.sections.count + 1) * 3;
          }
          
          - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
          {
              if (section % 3 != 1) {
                  return 0;
              }
              section = section / 3;
              ...
          }
          
          - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
          {
              if (section % 3 != 0) {
                  return nil;
              }
              section = section / 3;
              ...
          }
          
          - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
          {
              if (section % 3 != 0) {
                  return 0;
              }
              section = section / 3;
              ...
          }
          
          - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
          {
              if (section % 3 != 2) {
                  return 0;
              }
              section = section / 3;
              ...
          }
          
          - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
          {
              if (section % 3 != 0) {
                  return nil;
              }
              section = section / 3;
              ...
          }
          
          - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
          {
              if (section % 3 != 2) {
                  return nil;
              }
              section = section / 3;
              ...
          }
          
          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
          {
              int section = indexPath.section;
              section = section / 3;
              ...
          }
          

          【讨论】:

            【解决方案15】:

            现在分组样式看起来与 iOS 7 中的普通样式基本相同(在平整度和背景方面),对我们来说,最好和最简单(即最少 hacky)的解决方法是简单地将表格视图的样式更改为分组.当我们在顶部集成一个滚动导航栏时,使用 contentInsets 一直是个问题。使用分组表视图样式,它看起来完全一样(与我们的单元格)并且节标题保持固定。没有滚动怪异。

            【讨论】:

            • 这是最好的解决方案,特别是如果单元格是自定义的,当滚动到达顶部时,它似乎只是停止“保持”部分标题。
            【解决方案16】:

            只需更改 TableView 样式:

            self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];
            

            UITableViewStyle Documentation:

            UITableViewStylePlain- 一个普通的表格视图。任何部分的页眉或页脚都显示为内联分隔符,并在表格视图滚动时浮动。

            UITableViewStyleGrouped- 一个表视图,其部分呈现不同的行组。部分页眉和页脚不浮动。

            【讨论】:

            • 很好的答案,为我工作。无需任何工作
            【解决方案17】:

            更改您的 TableView 样式:

            self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];
            

            根据苹果的 UITableView 文档:

            UITableViewStylePlain- 一个普通的表格视图。任何节标题或 页脚显示为内联分隔符并在表格时浮动 视图被滚动。

            UITableViewStyleGrouped - 一个表格视图,其部分呈现不同 行组。部分页眉和页脚不浮动。希望 这个小小的改变会帮助你..

            【讨论】:

              【解决方案18】:

              @awulf 答案的 Swift 版本,效果很好!

              func scrollViewDidScroll(scrollView: UIScrollView) {
                  let sectionHeight: CGFloat = 80
                  if scrollView.contentOffset.y <= sectionHeight {
                      scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
                  }else if scrollView.contentOffset.y >= sectionHeight {
                      scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
                  }
              }
              

              【讨论】:

                【解决方案19】:

                从情节提要中 tableView 的属性检查器中选择分组表视图样式。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-11-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多