【问题标题】:UITableView: the proper way to display a separator for the last cellUITableView:显示最后一个单元格分隔符的正确方法
【发布时间】:2013-11-15 01:27:57
【问题描述】:

问题是在表格/部分的最后一个单元格中显示分隔符的最正确方法是什么。

基本上这就是我所追求的。

这是来自原生音乐应用程序,这让我觉得应该可以通过UITableView来实现,他们不会使用一些私有API来进行单元格分隔,对吧?

我知道你可以不使用实际的分隔符,但在单元格底部添加一条像素线。但我不喜欢这种方法,因为

  1. 当一个单元格被选中/突出显示时,分隔符上一个单元格的分隔符会自动隐藏(参见第二个屏幕截图,带有“你一定是疯了”选中)。这是 如果我使用单像素线,我希望 UITableView 处理而不是自己做的事情 (当单元格分隔器没有全部延伸时,这特别方便 到表格视图边缘的方式、分隔符和选定的单元格背景一起看起来不太好)。
  2. 我想让我的单元格尽可能平坦以提高滚动性能。

在 UITableView 参考中也有一些东西让我觉得有一种简单的方法可以得到我想要的东西:

在 iOS 7 及更高版本中,单元格分隔符不会一直延伸到 表视图的边缘。此属性设置所有的默认插入 表格中的单元格,很像 rowHeight 设置默认高度 细胞。 它还用于管理绘制的“额外”分隔符 普通样式表的底部。

有人知道如何准确地使用这些在普通样式表底部绘制的“额外”分隔符吗?因为这正是我需要的。 我认为将separatorInset 分配给UITableView,而不是UITableViewCell 可以解决问题,但事实并非如此,最后一个单元格仍然缺少分隔符。

现在我只看到一个选项:使用自定义部分页脚来模拟最后一个单元格的分隔符。这并不好,尤其是如果您想使用tableView:titleForFooterInSection: 方法获得实际的节页脚。

【问题讨论】:

  • 所以...让我看看我是否理解正确。您希望在其下方显示最后一个单元格的分隔符,对吗?
  • 是的,完全正确。我也希望它具有自定义插图,并在选择单元格时很好地消失。
  • 这个问题的答案很好:stackoverflow.com/a/50354801/4362465;它对我有用,我希望它也能帮助你:)

标签: ios objective-c uitableview ios7


【解决方案1】:

我使用“分组”的表格视图样式添加了这一行:

此外,它避免了在滚动时将最后一个分隔线粘贴在屏幕上!

【讨论】:

    【解决方案2】:

    当您将 headerView 或 footerView 添加到 TableView 时,最后的分隔线将消失。

    下面的示例将让您解决在最后一个单元格上显示分隔符的方法。你唯一需要实现的就是让这个分隔符在选择单元格后消失,所以其他单元格的行为是一样的。

    对于 Swift 4.0

    override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    
        let result = UIView()
    
        // recreate insets from existing ones in the table view
        let insets = tableView.separatorInset
        let width = tableView.bounds.width - insets.left - insets.right
        let sepFrame = CGRect(x: insets.left, y: -0.5, width: width, height: 0.5)
    
        // create layer with separator, setting color
        let sep = CALayer()
        sep.frame = sepFrame
        sep.backgroundColor = tableView.separatorColor?.cgColor
        result.layer.addSublayer(sep)
    
        return result
    }
    

    【讨论】:

    • @ironRoei 我很高兴 :)
    • 非常好。谢谢。
    【解决方案3】:

    所以这是 Swift 4 中的一个超级简单的解决方案:

    override func viewDidLoad(){}里面,我简单实现了这行代码:

        self.tableView.tableFooterView = UIView(frame: .zero)
    

    因此它确保只有最后一个单元格插入分隔符。

    这对我很有效,希望对你也有效!

    【讨论】:

      【解决方案4】:

      斯威夫特 3

      我发现了这个老问题,所以我在 Swift 中尝试了同样的方法:

          tableView.tableFooterView = UIView()
          tableView.tableFooterView?.height = 0 // Maybe not necessary
      

      但这会导致另一个问题(在我的情况下)。所以我以不同的方式解决了它。我在本节末尾添加了一个额外的单元格,为空且高度为零:

          override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return previousNumberOfRows + 1
          }
      
          override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return indexPath.row == previousNumberOfRows ? 0 : previousCellHeight
          }
      
          override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            if indexPath.row == items.count {
              return UITableViewCell()
          } else {
             previousCellInitialization()
          }
      

      这是一个不太简洁的解决方案,但适用于更多情况,如果您有多个部分,现有的页脚视图...

      【讨论】:

      • 我相信当您实际拥有页脚视图时,这是获得底部分隔符的唯一方法。谢谢!
      【解决方案5】:

      下面的代码对我有用:

      UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 0.35)];
      footerView.backgroundColor = [UIColor whiteColor];
      CGRect frame = footerView.frame;
      frame.origin.x = 15;
      frame.size.width = frame.size.width - 15;
      UIView *blackView = [[UIView alloc] initWithFrame:frame];
      [blackView setBackgroundColor:[UIColor blackColor]];
      blackView.alpha = 0.25;
      [footerView addSubview:blackView];
      tableView.tableFooterView = footerView;
      

      希望它也对你有用。

      【讨论】:

        【解决方案6】:

        这绝对是有帮助的。在职的。 但从属性检查器中设置分隔符“无”。 在 cellForRowAtIndexPath 方法中编写以下代码

        if(indexPath.row==arrData.count-1){
         UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,           
         cell.contentView.frame.size.height - 1.0,      
         cell.contentView.frame.size.width, 1)];
        
            lineView.backgroundColor = [UIColor blackColor];
            [cell.contentView addSubview:lineView];
        }
        

        【讨论】:

          【解决方案7】:

          适用于 iOS 7.x 和 8.x(放入 cellForRowAtIndexPath):

          (PS 用您的数组数据源计数替换“数据源的最大元素”)

           if (row == <max elements of your datasource>-1) {
               UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height-1, self.view.frame.size.width, 1)];/// change size as you need.
               separatorLineView.tag = 666;
               separatorLineView.backgroundColor = [UIColor colorWithRed: 204.0/255.0 green: 204.0/255.0 blue: 204.0/255.0 alpha:1.0];
               UIView *separator = [cell.contentView viewWithTag:666];
               // case of orientation changed..
               if (separator.frame.size.width != cell.contentView.frame.size.width) {
                  [[cell.contentView viewWithTag:666] removeFromSuperview];
                  separator = nil;
               }
               if (separator==nil) [cell.contentView addSubview:separatorLineView];
           }
          

          【讨论】:

            【解决方案8】:

            这对我来说完美无缺,可以在最后一个单元格中添加分隔符。玩得开心!

            self.tableView.tableFooterView = [[UIView alloc] init];
            

            【讨论】:

            • 我不得不删除 viewForFooterInSection 和 heightForFooterInSection 的实现,它起作用了。
            【解决方案9】:

            如果您添加一个空页脚,那么表格视图将删除所有剩余的行分隔符(对于不存在的单元格),但仍会包括最后一个单元格的分隔符:

            - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
            {
                return [UIView new]; 
            }
            

            【讨论】:

              【解决方案10】:

              在 iOS 8 中,如果你有一个普通样式的 UITableView,并添加一个页脚,最后一个分隔符就没有了。但是,您可以通过向页脚添加自定义分隔视图轻松地重新创建它。

              此示例完全模仿 Today Widget 分隔符样式

                  override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
              
                      //create footer view
                      let result = UIView()
                      result.frame.size.height = tableView.rowHeight
              
                      //recreate last cell separator, which gets hidden by footer
                      let sepFrame = CGRectMake(15, -0.5, tableView.frame.width, 0.5);
                      let vibrancyEffectView = UIVisualEffectView.init(effect: UIVibrancyEffect.notificationCenterVibrancyEffect())
                      vibrancyEffectView.frame = sepFrame
                      vibrancyEffectView.contentView.backgroundColor = tableView.separatorColor
                      result.addSubview(vibrancyEffectView)
                      return result
              }
              

              【讨论】:

              • 这确实有效,但是对于 Swift 2.3,我无法使用这一行 let vibrancyEffectView = UIVisualEffectView.init(effect: UIVibrancyEffect.notificationCenterVibrancyEffect()) 所以我用这一行替换了它 let vibrancyEffectView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: UIBlurEffect(style: UIBlurEffectStyle.ExtraLight))) 很好的答案!
              【解决方案11】:

              我刚刚找到了适合我的东西。简而言之:给你的 UITableView 一个 tableFooterView 并将它的框架高度设置为 0。这会显示一个实际的分隔符,并带有正确的插图。

              详细说明:如果您使用故事板,请将 UIView 拖到 Table View 的底部(在左侧的树视图中),使其显示在 Table View Cell 下方,处于相同的层次结构。这将创建一个 tableFooterView。当然,这也可以通过编程方式完成。

              然后,在你的 UITableViewController 的实现中:

              UIView *footerView = self.tableView.tableFooterView;
              CGRect footerFrame = footerView.frame;
              footerFrame.size.height = 0;
              [footerView setFrame:footerFrame];
              

              让我知道这是否适合你!如果您改用 tableHeaderView,它也可能适用于第一个分隔符,但我还没有尝试过。

              【讨论】:

              • 我只是在 heightForFooterInSection 方法中返回了高度 0。这将显示所有单元格的边缘插图(即使是未填充的单元格)。对我来说,这很有效,但对于这个问题的发布者来说,这不是一个可行的解决方案。
              • 我相信这是不做任何骇人听闻的事情的答案。它的工作原理是给我最后一个单元格的分隔符,但删除其余的空单元格。
              【解决方案12】:

              如果你不使用部分,你可以这样做:

              - (void)viewDidLoad
              {
                   self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(insetLeftSide, 0, width - insetRightSide, 1)];
              }
              

              如果您使用部分,则将每个部分中的页脚实现为方法中的一个点视图

              - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
              {
              }
              
              - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
              {
              }
              

              这将允许您为最后一个单元格设置一个分隔符,实际上它不是分隔符而是一个页脚,您可以使用它并使其看起来像一个分隔符

              【讨论】:

                【解决方案13】:

                我遇到了类似的问题并找到了解决方法。 Apple 会隐藏最后一个 uitableviewcell 分隔符,然后在您选择单元格或在该单元格上调用 select 和取消选择时显示它。

                所以我教的最好的是- (void)layoutSubviews。分隔视图称为_separatorView,它是私有属性。使用单元格的选定/突出显示状态,您可以想出如下内容:

                - (void)layoutSubviews
                {
                    // Call super so the OS can do it's layout first
                    [super layoutSubviews];
                
                    // Get the separator view
                    UIView *separatorView = [self valueForKey:@"_separatorView"];
                    // Make the custom inset
                    CGRect newFrame = CGRectMake(0.0, 0.0, self.bounds.size.width, separatorView.frame.size.height);
                    newFrame = CGRectInset(newFrame, 15.0, 0.0);
                    [separatorView setFrame:newFrame];
                
                    // Show or hide the bar based on cell state        
                    if (!self.selected) {
                        separatorView.hidden = NO;
                    }
                    if (self.isHighlighted) {
                        separatorView.hidden = YES;
                    }
                }
                

                类似的东西。

                【讨论】:

                • 谢谢你的回答,但我宁愿在self的底部画一条1像素的线,也不愿使用私有API。但是你的建议确实有效,所以我对你的答案进行投票,尽管我不接受它,因为我仍然希望有人向我解释什么是 “它也用于管理在普通样式表的底部” 意味着和锄头在我的情况下使用它。
                • 您可以使用 layoutSubviews 来查看该 _separatorView 对象的 hidden 属性。我认为隐藏它是“预期的行为”,除非它不在屏幕上。
                【解决方案14】:

                这将完全符合您的要求.. 即使该行将占据单元格的整个宽度:

                - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

                self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
                self.tableView.separatorColor = [UIColor redColor];
                self.tableView.separatorInset = UIEdgeInsetsZero;
                

                【讨论】:

                • 这就是问题所在,UIEdgeInsetsZero 不是我需要的。他们确实在原生音乐中为 separatorInset = UIEdgeInsetsMake(0., 15., 0., 15.) 工作,所以一定有办法。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-12-16
                相关资源
                最近更新 更多