我们想要什么
可以动态打开和关闭的表格视图标题。
解决方案 1:没有接口构建器
class ViewController: UIViewController {
var headerView = UIView()
var tableView = UITableView()
var isHeaderOpen = false
let HEADER_CLOSED_HEIGHT: CGFloat = 100
let HEADER_OPEN_HEIGHT: CGFloat = 200
var headerClosedHeightConstraint: NSLayoutConstraint!
var headerOpenHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
// Add the table view to the screen.
view.addSubview(tableView)
// Make the table view fill the screen.
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["tableView": tableView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["tableView": tableView]))
// Add the header view to the table view.
tableView.tableHeaderView = headerView
headerView.backgroundColor = UIColor.redColor()
headerView.translatesAutoresizingMaskIntoConstraints = false
// Add a button to the header.
let button = UIButton(type: .Custom)
button.setTitle("Toggle", forState: .Normal)
headerView.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[button]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
headerView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[button]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
button.addTarget(self, action: "toggleHeaderAction:", forControlEvents: .TouchUpInside)
// Make the header full width.
view.addConstraint(NSLayoutConstraint(item: headerView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0))
// Create the constraints for the two different header heights.
headerClosedHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 0, constant: HEADER_CLOSED_HEIGHT)
// Create the height constraint for the header's other height for later use.
headerOpenHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: HEADER_OPEN_HEIGHT)
closeHeader() // Close header by default.
}
func openHeader() {
headerView.removeConstraint(headerClosedHeightConstraint)
headerView.addConstraint(headerOpenHeightConstraint)
updateHeaderSize()
isHeaderOpen = true
}
func closeHeader() {
headerView.removeConstraint(headerOpenHeightConstraint)
headerView.addConstraint(headerClosedHeightConstraint)
updateHeaderSize()
isHeaderOpen = false
}
func updateHeaderSize() {
// Calculate the header's new size based on its new constraints and set its frame accordingly.
let size = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
var frame = headerView.frame
frame.size.height = size.height
headerView.frame = frame
tableView.tableHeaderView = headerView
self.headerView.layoutIfNeeded()
}
func toggleHeader() {
if isHeaderOpen {
closeHeader()
} else {
openHeader()
}
}
func toggleHeaderAction(sender: AnyObject) {
toggleHeader()
}
}
解决方案 2:使用 INTERFACE BUILDER
要使UITableView 标头动态更改高度,请尝试以下操作。
在您的故事板中,首先将UITableView 添加到您的视图控制器。然后添加一个UIView 作为UITableView 的第一个孩子(接口生成器自动将其解释为UITableView 的标题视图)。
将插座连接到表格和标题,以便我们稍后在代码中访问它们。
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var headerView: UIView!
接下来,我们在代码中创建两个约束(打开和关闭),稍后我们将添加/删除它们以切换标题的高度。
var headerOpenHeightConstraint: NSLayoutConstraint!
var headerClosedHeightConstraint: NSLayoutConstraint!
我们还要创建一个标志来跟踪标头的打开/关闭状态。另外,我们指定打开的标题高度。
var isHeaderOpen = false
let HEADER_OPEN_HEIGHT: CGFloat = 200
Interface Builder 会自动将我们创建的 header 的尺寸转换为 Auto Layout 约束。由于我们要自己更改标题的高度,我们需要添加自己的替换约束并删除这些自动约束(NSAutoresizingMaskLayoutConstraints)。
在viewDidLoad()中,添加如下内容(默认header高度为闭合高度,HEADER_OPEN_HEIGHT为openheader高度)。
override func viewDidLoad() {
super.viewDidLoad()
// The header needs a new width constraint since it will no longer have the automatically generated width.
view.addConstraint(NSLayoutConstraint(item: headerView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1, constant: 0))
// Add the height constraint for the default state (closed header).
headerClosedHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: headerView.bounds.height)
headerView.addConstraint(headerClosedHeightConstraint)
// Make the constraint we'll use later to open the header.
headerOpenHeightConstraint = NSLayoutConstraint(item: headerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: HEADER_OPEN_HEIGHT)
// Finally we disable this so that we don't get Interface Builder's automatically generated constraints
// messing with our constraints.
headerView.translatesAutoresizingMaskIntoConstraints = false
}
最后,在 Interface Builder 中,添加一个按钮并将其连接到视图控制器中的操作。
@IBAction func toggleHeaderAction(sender: AnyObject) {
// Add/remove the appropriate constraints to toggle the header.
if isHeaderOpen {
headerView.removeConstraint(headerOpenHeightConstraint)
headerView.addConstraint(headerClosedHeightConstraint)
} else {
headerView.removeConstraint(headerClosedHeightConstraint)
headerView.addConstraint(headerOpenHeightConstraint)
}
// Calculate the header's new size based on its new constraints.
let size = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
// Give the header its new height.
var frame = headerView.frame
frame.size.height = size.height
headerView.frame = frame
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
tableView.tableHeaderView = headerView
isHeaderOpen = !isHeaderOpen
}