【问题标题】:Setting tableView header's height in Swift在 Swift 中设置 tableView 标题的高度
【发布时间】:2015-10-18 09:30:36
【问题描述】:

我正在尝试在表格视图控制器中设置原型单元格顶部的视图高度。我使用 IB 设置它的高度(尺寸检查器)并将其设置为 61,如下所示(绿色视图是“标题”视图):

但每当我运行该应用程序时,它的高度最终都是568.0。我有一个名为 testUIView 的 IBOutlet 用于我的表视图控制器中的视图,我这样做:println("testUIView Height->\(testUIView.frame.height)") 并且确实在运行时最终成为 568.0

这是一个屏幕截图,显示了它在运行时的高度:

所以我的问题是:如何设置视图的高度,使其在运行时为 61,这样它确实看起来像我的第一个屏幕截图(按大小)?

我试图在override func viewWillLayoutSubviews() 中设置它的'height 属性,但它不允许我为高度testUIView.frame.height = CGFloat(61.0) 赋值。

任何帮助表示赞赏!提前致谢!

干杯!

【问题讨论】:

  • 您没有为表格视图使用标题是否有原因?
  • 其实不行,不好意思问了,怎么用?

标签: ios swift xcode uitableview uiview


【解决方案1】:

这是一个使用部分标题视图而不是实际表标题视图的解决方案:


如果您想为您的 UITableView 使用标题,您可以在 Interface Builder 中设计另一个原型单元格,基于 UITableViewCell 创建一个自定义类,并将其分配给类检查器的界面构建器中的原型单元格。

然后在你的控制器中使用

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?

在该函数中,您实际上要从表格视图中创建一个可重用的单元格,但将其转换为您为标题创建的自定义单元格。您将可以像常规 UITableViewCell 一样访问它的所有属性,然后您只需返回单元格的视图

return cell.contentView

你要使用的另一种方法是

func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 61.0
}

这个很容易解释。

斯威夫特 3.0.1

public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 61.0
}

【讨论】:

  • 谢谢!有效!我想问的另一件事是......你知道任何让它始终保持在导航栏下方的技术,即不与其余单元格一起滚动吗?还是不可能?
  • 这已经为您提供了保障:stackoverflow.com/questions/17582818/… - 很高兴它成功了!
  • 感谢您的链接!关于代码......你知道哪个部分与我想要实现的目标相关吗?我试了一下,但不知道它会使用哪种方法。抱歉问得太多了,但我真的不了解 Objective-C,我迷失在所有这些方括号中......
  • 没问题,我实际上认为您在情节提要上设置了组或普通属性。要在代码中执行此操作,您将使用: newTableView.style = UITableViewStyle.Plain 其中“newTableView”与 tableView 的 IBOutlet 的名称匹配。
  • 搞定了,非常感谢!嘿......所以你的方法有效,但我刚刚意识到,每当我在表格视图中向下/向上滚动时,你实际上可以在表格视图的右侧看到“高度指示器”(你可以看到你所在的位置表格视图)甚至在标题单元格中。我理想的方法是让导航栏看起来像一个视图,这样你就看不到你实际上是在标题视图中滚动。我希望它充当可以在 tableViewControllers 之间切换的子菜单,这是分段控制控件提供的那种功能
【解决方案2】:

Swift 3/Xcode 8:

将此添加到viewDidLoad()

let HEADER_HEIGHT = 100
tableView.tableHeaderView?.frame.size = CGSize(width: tableView.frame.width, height: CGFloat(HEADER_HEIGHT))

享受吧!

【讨论】:

  • 谢谢。试图直接设置高度并且得到“高度”是一个只能获取的属性
【解决方案3】:

接受的答案实际上并没有回答问题。相反,它通过使用 SECTION 标头提供了替代方案。其他人已经回答了这个问题,但我将在此处复制答案并提供更多说明。


加载视图

表格视图与 iPhone 一样古老,因此有时您必须强制它执行您想要的操作。

首先我们需要加载标题并手动设置它的高度。否则视图会占用比它需要的更多的高度。我们在 viewDidLayoutSubviews 回调上执行此操作:

lazy var profileHeaderView: ProfileHeaderView = {
    let headerView = ProfileHeaderView()
    return headerView
}()

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    sizeHeaderToFit()
}

private func sizeHeaderToFit() {
    profileHeaderView.setNeedsLayout()
    profileHeaderView.layoutIfNeeded()

    var frame = profileHeaderView.frame
    frame.size.height = profileHeaderView.calculateHeight()
    profileHeaderView.frame = frame

    tableView.tableHeaderView = profileHeaderView
}

如您所见,我喜欢将视图放在惰性变量中。这可确保它们始终被创建,但仅在我开始使用它们时才创建。

您还可以看到我正在计算高度。在某些情况下,您的高度是固定的,因此您只需将帧高度设置为硬编码值。


设置一些优先级

我们可能会在调试器中看到一些约束警告。发生这种情况是因为表格视图在使用我们上面指定的大小之前首先强制为 0x0 大小。此时,您的约束和视图的高度相互冲突。

要清除这些,我们只需设置约束优先级。首先,您应该将标题视图组件包装在另一个视图中(我通常总是为标题视图这样做)。这将使您在标题视图上更轻松地管理约束。

然后我们需要将底部约束优先级设置为高:

containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)

这是一个更完整的例子:

警告:认为它仍可用作布置视图的指南,如果您使用 nib 或情节提要创建视图,请不要使用此代码。

class ProfileHeaderView: UIView {
    lazy var containerView: UIView = {
        let view = UIView()
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        // We do this because the view is not created using storyboards or nibs.
        fatalError("init(coder:) has not been implemented")
    }

    private func setupLayout() {
        self.addSubview(containerView)

        containerView.translatesAutoresizingMaskIntoConstraints = false
        containerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        containerView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
        containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        containerView.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
        containerView.setContentHuggingPriority(.defaultHigh, for: .vertical)

        // Set the rest of your constraints against your containerView not self and add your subviews to your containerView not self
    }
}

以下是使用 snap-kit 设置约束的示例:

containerView.snp.makeConstraints() { make in
    make.top.equalTo(self.snp.top)
    make.leading.equalTo(self.snp.leading)
    make.trailing.equalTo(self.snp.trailing)
    make.bottom.equalTo(self.snp.bottom).priority(.high)
}

确保将约束添加到 containerView 而不是 self 并使用 containerView 添加子视图和其余约束。

【讨论】:

    【解决方案4】:

    在 swift 4.1 和 Xcode 9.4.1 中

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
         if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad {
            return 75.0
          } else {
            return 50.0
          }
    }
    

    【讨论】:

      【解决方案5】:

      这一定是 iOS 中最奇怪的问题之一。

      如果您只是想要一个固定的高度,从 2019 年开始,您可以:

      public override func viewDidLayoutSubviews() {
          var frame = tableView.tableHeaderView!.frame
          frame.size.height = 68
          tableView.tableHeaderView!.frame = frame
      }
      

      奇怪的东西。

      【讨论】:

        猜你喜欢
        • 2016-08-05
        • 2016-10-19
        • 2019-11-01
        • 1970-01-01
        • 2020-07-06
        • 2015-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多