【问题标题】:How to customize tableView separator in iPhone如何在 iPhone 中自定义 tableView 分隔符
【发布时间】:2010-11-25 09:20:57
【问题描述】:

默认情况下,uitableview 中有一个单行分隔符。

但我想把我自定义的行作为分隔符。

有可能吗?怎么样?

【问题讨论】:

    标签: iphone uitableview


    【解决方案1】:

    如果您想做的不仅仅是使用UITableViewseparatorColor 属性更改分隔符的颜色,那么您可以将separatorStyle 属性设置为UITableViewCellSeparatorStyleNone,然后:

    • 创建自定义UITableViewCells,其中包含您的自定义分隔符
    • 创建包含自定义分隔符的备用 [UITableViewCell][6]

    例如,如果您的表格当前显示 5 行,您可以将其更新为显示 9 行,索引 1、3、5、7 处的行将是分隔单元格。

    【讨论】:

    • 非常反对使用单元格作为分隔符。这很难看,但我推荐子类化 UITableViewCell 和覆盖 layoutSubviews。 stackoverflow.com/questions/12509747/…
    • @CameronLowellPalmer 在某些情况下使用单元格作为分隔符是完美的。事实上,我们只想要一个 3 点宽的透明分隔符。放入隐形的间隔电池非常适合!
    【解决方案2】:

    更好的解决方案是使用单元格的当前宽度和高度。像这样的:

    UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height - 1.0, cell.contentView.frame.size.width, 1)];
    
    lineView.backgroundColor = [UIColor darkGrayColor];
    [cell.contentView addSubview:lineView];
    

    【讨论】:

    • 如果你有一个包含大量单元格的滚动表格视图,这将继续添加子视图,因为当用户滚动表格视图时单元格会被回收。不是一个好的解决方案。
    • -1 对于这个解决方案,因为我同意上面的评论。如果您有超过 10 个左右的单元格(并且您正在重用/出列它们),这是一个糟糕的解决方案,因为您在一个单元格上使用的分隔符会在该单元格被重用时出现,而这可能不是您想要的。
    • @Matjan 如果将这些行放在单元格的 init(或其 contentView 的 init)中,那么这怎么会发生,因此只添加一次?回收的单元格将使用此分隔符出列,您唯一需要做的就是更新单元格的 contentView 数据。
    • @BenPatch 虽然考虑这种情况很好,但它并不关心这个问题的特定答案,因为 OP 只想使用一些自定义视图。此外,如果您使用约束并将分隔符粘贴到单元格内容视图的底部,恕我直言,这将是您可以使用自定义分隔符获得的最预期行为。现在,如果您不使用任何特定类型的 UITableViewCell 子类,这可能是正确的,但如果您要使特定类型的单元格出列,则分隔符在其中的位置也是预期的。您能否详细说明一下这些示例?
    【解决方案3】:

    如果您需要为不同的行使用不同的分隔符颜色,或者您希望在点击时突出显示该行时分隔符保持可见,请尝试以下操作:

    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    
    // We have to use the borderColor/Width as opposed to just setting the 
    // backgroundColor else the view becomes transparent and disappears during 
    // the cell's selected/highlighted animation
    UIView *separatorView = [[UIView alloc] initWithFrame:CGRectMake(0, 43, 1024, 1)];
    separatorView.layer.borderColor = [UIColor redColor].CGColor;
    separatorView.layer.borderWidth = 1.0;
    [cell.contentView addSubview:separatorView];
    

    这假定您的单元格的背景颜色是透明的。


    上述解决方案来自一些广泛的实验。以下是关于我的发现的一些注释,我相信它们会对人们有所帮助:

    处于正常的“未选中”状态

    • contentView(您的 XIB 中的内容,除非您另外编写代码)正常绘制
    • selectedBackgroundView 是隐藏的
    • backgroundView 是可见的(所以如果你的 contentView 是透明的,你会看到 backgroundView 或者(如果你没有定义 backgroundView,你会看到 UITableView 本身的背景颜色)

    选择了一个单元格,以下内容立即发生,没有任何动画:

    • contentView 中的所有视图/子视图都将其背景颜色清除(或设置为透明)、标签等文本颜色更改为所选颜色
    • selectedBackgroundView 变为可见(此视图始终是单元格的完整大小(忽略自定义框架,如果需要,请使用子视图)。还要注意子视图的背景颜色由于某种原因不显示,也许它们像 contentView 一样重新设置透明)。如果您没有定义 selectedBackgroundView,那么 Cocoa 将创建/插入蓝色(或灰色)渐变背景并为您显示)
    • backgroundView 不变

    当取消选择单元格时,将开始动画移除突出显示:

    • selectedBackgroundView alpha 属性从 1.0(完全不透明)动画到 0.0(完全透明)。
    • backgroundView 再次保持不变(因此动画看起来像是 selectedBackgroundView 和 backgroundView 之间的交叉淡入淡出)
    • 只有在动画完成后,contentView 才会在“未选中”状态下重新绘制,并且其子视图背景颜色会再次可见(这可能会导致您的动画看起来很糟糕,因此建议您不要使用 UIView。 contentView 中的背景颜色)

    【讨论】:

      【解决方案4】:

      这些答案导致突出显示的矩形被您添加到单元格的分隔符覆盖(至少在 iOS 6 上经过我的测试)。您需要将separatorColor 设置为[UIColor clearColor] 以使单元格仍然相隔1px,然后您可以在间隙中绘制分隔符:

      - (void)viewDidLoad {
          self.tableView.separatorColor = [UIColor clearColor];
      }
      
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
          // snip
          CALayer *separator = [CALayer layer];
          separator.backgroundColor = [UIColor redColor].CGColor;
          separator.frame = CGRectMake(0, 43, self.view.frame.size.width, 1);
          [cell.layer addSublayer:separator];
          return cell;
      }
      

      【讨论】:

      • 这会为当前视图创建一条线。当屏幕旋转到横向时,它会太短。为此,您需要添加约束。
      • 我还建议调用 super.viewDidLoad()
      【解决方案5】:

      您添加以下代码cellForRowAtIndexPath tableView 的委托来为everyCell创建一个高度为 1 像素、宽度为 200 像素的自定义图像视图

      UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 1)];
      lineView.backgroundColor = [UIColor blackColor];
      [cell.contentView addSubview:lineView];
      

      注意:我不知道这对性能有多大影响。

      【讨论】:

      • 不确定它有多大的不同,但我把它放在 tableView 的 willDisplayCell 委托中。
      【解决方案6】:

      我不知道这是否可以通过某些设置“自动”完成。但建议将行分隔符设置为无,并在单元格的边框中实际绘制您想要的行分隔符..

      【讨论】:

        【解决方案7】:

        如果您在 Swift 中使用自定义单元格:另一种方法是使用可以在该单元格顶部绘制一条线的函数来扩展 UITableViewCell。

        import UIKit
        
        extension UITableViewCell {
            func addSeparatorLineToTop(){
                let lineFrame = CGRectMake(0, 0, bounds.size.width, 1)
                let line = UIView(frame: lineFrame)
                line.backgroundColor = UIColor.myGray_300()
                addSubview(line)
            }
        }
        

        然后您可以将此行添加到任何自定义单元格中,例如在 awakeFromNib 中

        override func awakeFromNib() {
            super.awakeFromNib()
            addSeparatorLineToTop()
        }
        

        这个解决方案很好,因为它不会弄乱您的故事板并将您的额外代码限制为 1 行。

        【讨论】:

        • CGRectMake 已弃用,请改用 CGRect
        【解决方案8】:

        在 Retina 显示器上,由于抗锯齿,即使绘制 0.5 个单位的线也会产生两个像素的线。要将其渲染为两个显示器上的单个像素,请将其上移四分之一单位:

        UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, self.contentView.frame.size.height - (1.0 - 0.25), self.contentView.frame.size.wi
        lineView.backgroundColor = [UIColor colorWithRed:(230.0/255.0f) green:(233/255.0f) blue:(237.0/255.0f) alpha:1.0f];
        [self.contentView addSubview:lineView];
        

        【讨论】:

          【解决方案9】:

          在 iOS 7 (GM) 上测试:

          @implementation MyTableViewController
          
          - (void)viewDidLayoutSubviews {
              for (UIView *view in self.view.subviews) {
                  if ([view isKindOfClass:NSClassFromString(@"_UITableViewCellSeparatorView")])
                      view.backgroundColor = [UIColor redColor];
              }
          }
          
          @end
          

          注意:在某些配置中,UITableView 分隔符移动到单元格,这将导致此代码无法工作,除非您也进入所有 UITableViewCells。

          【讨论】:

          • 当我来到这里搜索 _UITableViewCellSeparatorView 时,我相信我可能遇到了与您类似的问题。我有一个适用于 iOS 6 的自定义分隔符实现,但在 iOS 7 中似乎除了我的之外还显示了默认分隔符。将分隔符样式设置为 UITableViewCellSeparatorStyleNone 会导致两者都消失。您能否进一步解决您的问题?
          • 它使用私有 API,可能会导致应用被拒绝,也可能在未来的任何 iOS 版本中中断。
          • 它不是私有 API。但是您仍然应该小心它,因为您是对的,它是私有视图层次结构并且可能随时更改。然而,这仅仅是美学上的,并且是安全的。
          • 这是一个私有 API - 请注意您正在使用的 _UITableViewCellSeparatorView 类名开头的下划线。此外,您甚至无法访问.h 文件中的类声明。它可以很容易地更改为,比方说,_UITableViewCellSeparatorView**2** 在任何未来的版本中,恕不另行通知,这种方法会失败。
          • 它不是私有 API,我们没有调用私有方法。然而,这视图的私有视图层次结构,正如你所说,它可能随时改变。我提供了这个例子,因为有时这是你唯一的选择。您必须决定是否要冒应用程序无法设置样式分隔符的风险。但是没有被拒绝的风险,因为您没有调用任何私有 API。我的例子没有崩溃的风险。
          【解决方案10】:

          Swift 版本:

          private let kSeparatorTag = 123
          private let kSeparatorHeight: CGFloat = 1.5
          
          func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
          {
              if cell.viewWithTag(kSeparatorTag) == nil //add separator only once
              {
                  let separatorView = UIView(frame: CGRectMake(0, cell.frame.height - kSeparatorHeight, cell.frame.width, kSeparatorHeight))
                  separatorView.tag = kSeparatorId
                  separatorView.backgroundColor = UIColor.redColor()
                  separatorView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
          
                  cell.addSubview(separatorView)
              }
          }
          

          【讨论】:

            【解决方案11】:

            下面 gist 中的单元格是 UITableViewCell 的子类,其中每个单元格可以有自己的分隔符和多种样式(目前仅支持 .None 和 .Default )。 它是用 Swift 编写的,并假定使用 Autolayout。

            https://gist.github.com/evgeniyd/fa36b6f586a5850bca3f

            如何使用类:

            1. 将 UITableView 对象的分隔符样式设置为UITableViewCellSeparatorStyle.None

              tableView.separatorStyle = .None
              
            2. 创建MPSTableViewCell的子类

            3. awakeFromNib() 内部某处设置单元格的分隔符样式

            注意:下面的代码假设单元格是从 xib/storyboard 加载的

                class FASWorkoutCell: FASTableViewCell {
            
                required init(coder aDecoder: NSCoder) {
                     super.init(coder: aDecoder)
                 }
            
                 override func awakeFromNib() {
                     super.awakeFromNib()
            
                     separatorType = .Default
                 }
            
                 // ...
            
                 }
            

            【讨论】:

              【解决方案12】:

              如果你使用自定义的 UITableViewCell,你可以简单的在 UItableViewCell.xib 的底部添加 UIView 并将背景颜色设置为你想要的颜色。

              例如,在 xib 上,我在底部添加了一个 UIView,并将高度设置为 1。使用自动布局,我将左侧约束设置为 12,底部约束设置为 0,右侧约束设置为 0,高度设置为 1。

              【讨论】:

                猜你喜欢
                • 2017-01-25
                • 1970-01-01
                • 2011-01-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-11-23
                • 2020-09-08
                • 1970-01-01
                相关资源
                最近更新 更多