问题
I am trying to add UIControls to static TableViewHeaders in iOS using swift. The goal is build on top of the default appearance so the UI will match default UI elements going forward.
I found a great example of modifying the appearance of existing elements, but nothing on adding new ones.
My specific goals are:
- "Select All" functionality to quickly mark all rows in a section as "checked" (could be a checkmark accessory, UISwitch, etc)
- "Show/Hide" functionality to allow a single View to provide a simple "overview" by sections while still presenting access to details inside sections.
As both of these related to the section groupings, the headers are a logical choice for adding this functionality.
回答1:
There are two main options for customizing static headers for TableViews:
willDisplayHeaderView provides the default view and allows for modification of it. Simple appearance modifications are fairly straight forward. Adding interactive features such as buttons is a bit more complicated
viewForHeaderInSection returns the view for the header, which can be loaded from a nib or created entirely in code. One disadvantage of this is that it gives no access to the default appearance of headers, and Apple only provides access to one default (UIColor.groupTableViewBackground).
To build on top of the default header, willDisplayHeaderView needs to be used.
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
{
let header = view as! UITableViewHeaderFooterView
let headerLabelFont: UIFont = header.textLabel!.font
// References for existing or new button
var selectButton: UIButton? = nil
// Check for existing button
for i in 0..<view.subviews.count {
if view.subviews[i] is UIButton {
selectButton = view.subviews[i] as? UIButton
}
}
// No button exist, create new one
if selectButton == nil {
selectButton = UIButton(type: .system)
header.addSubview(selectButton!)
toggleButton = UIButton(type: .system)
header.addSubview(toggleButton!)
}
// Configure button
selectButton?.frame = CGRect(x: view.frame.size.width - 85, y: view.frame.size.height - 28, width: 77, height: 26)
selectButton?.tag = section
selectButton?.setTitle("SELECT ALL", for: .normal)
selectButton?.titleLabel?.font = UIFont(descriptor: headerLabelFont.fontDescriptor, size: 11)
selectButton?.contentHorizontalAlignment = .right;
selectButton?.setTitleColor(self.view.tintColor, for: .normal)
selectButton?.addTarget(self, action: #selector(self.selectAllInSection), for: .touchUpInside)
}
func selectAllInSection() {
...
The biggest challenge is working around the fact that static header cells can be reused by the TableView. So if one is modified, for example by adding a button, then when it is reused a second button could be added. This is only a problem if the TableView is large enough to scrolll off screen, but should be guarded against as the results can be tough to track down.
If multiple buttons are added to a header, some mechanism to identify each button is needed. The UIButton.tag is one option, but in this example that field is used to identify which section to act on. Another option would be to use the tag string to include two pieces of information.
A full working demo can be found on Github
(yes answering my own question, wanted to give something back after leaching for years)
来源:https://stackoverflow.com/questions/44735440/adding-buttons-to-static-tableview-headers-with-swift