Skip to content

Commit 3e31cb4

Browse files
committed
Update README.md
1 parent cb952a1 commit 3e31cb4

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed

README.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,126 @@
11
# ios-swift-collapsible-table-section
22
A simple iOS swift project demonstrates how to implement collapsible table section.
3+
4+
### Demo ###
5+
![demo](screenshots/demo.gif)<br />
6+
7+
### How to implement collapsible table sections? ###
8+
9+
#### Step 1. Prepare the Data ####
10+
11+
Let's say we have the following data that is grouped to different sections, each section is a `Section` object:
12+
13+
```swift
14+
struct Section {
15+
var name: String!
16+
var items: [String]!
17+
var collapsed: Bool!
18+
19+
init(name: String, items: [String]) {
20+
self.name = name
21+
self.items = items
22+
self.collapsed = false
23+
}
24+
}
25+
26+
var sections = [Section]()
27+
28+
sections = [
29+
Section(name: "Mac", items: ["MacBook", "MacBook Air", "MacBook Pro", "iMac", "Mac Pro", "Mac mini", "Accessories", "OS X El Capitan"]),
30+
Section(name: "iPad", items: ["iPad Pro", "iPad Air 2", "iPad mini 4", "Accessories"]),
31+
Section(name: "iPhone", items: ["iPhone 6s", "iPhone 6", "iPhone SE", "Accessories"])
32+
]
33+
```
34+
`collapsed` indicates whether the current section is collapsed or not, by default is `false`.
35+
36+
#### Step 2. Design the Header and Cell ####
37+
38+
Select the `Table View` in the story board, choose `Dynamic Prototypes` and set `Prototype Cells` to `2`, one for the custom header and one for the row cell, and assign the `Identifier` to `header` and `cell` respectively.
39+
40+
Add a UIButton (the toggler) and a Label to the header prototype cell, create a swift file which extends `UITableViewCell` and name it `CollapsibleTableViewHeader.swift`. The file is super simple, it defines two IBOutlets for the toggle button and label. Finally set the header cell class to our custom header `CollapsibleTableViewHeader` and link the IBOutlets.
41+
42+
Now the file should look like this:
43+
44+
```swift
45+
import UIKit
46+
47+
class CollapsibleTableViewHeader: UITableViewCell {
48+
49+
@IBOutlet var titleLabel: UILabel!
50+
@IBOutlet var toggleButton: UIButton!
51+
52+
}
53+
```
54+
55+
By creating a prototype cell and subclassing UITableViewCell, we have the following benefits:
56+
* We can visually design the custom header
57+
* We shouldn't need to create a nib and register it to the the tableView like the following, personally I don't like having a nib in my project and if we use `dequeueReusableHeaderFooterViewWithIdentifier`, seems like we can't have 0 rows in that section dynamically:
58+
```swift
59+
let nib = UINib(nibName: "TableSectionHeader", bundle: nil)
60+
tableView.registerNib(nib, forHeaderFooterViewReuseIdentifier: "TableSectionHeader")
61+
```
62+
63+
#### Step 3. The UITableViewDelegate ####
64+
65+
First the number of sections is `sections.count`:
66+
67+
```swift
68+
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
69+
return sections.count
70+
}
71+
```
72+
73+
For the number of rows in each section, we use `collapsed` property to control it, if `collapsed` is true, then return 0, otherwise return items count:
74+
75+
```swift
76+
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
77+
return (sections[section].collapsed!) ? 0 : sections[section].items.count
78+
}
79+
```
80+
81+
We use tableView's viewForHeaderInSection function to hook up our custom header:
82+
83+
```swift
84+
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
85+
let header = tableView.dequeueReusableCellWithIdentifier("header") as! CollapsibleTableViewHeader
86+
87+
header.titleLabel.text = sections[section].name
88+
header.toggleButton.tag = section
89+
header.toggleButton.addTarget(self, action: #selector(CollapsibleTableViewController.toggleCollapse), forControlEvents: .TouchUpInside)
90+
91+
header.toggleButton.rotate(sections[section].collapsed! ? 0.0 : CGFloat(M_PI_2))
92+
93+
return header.contentView
94+
}
95+
```
96+
97+
noticed that we register the touch up inside event for the toggler, once it's tapped, it will trigger the `toggleCollapse` function.
98+
99+
Last, the normal row cell is pretty straightforward:
100+
101+
```swift
102+
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
103+
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!
104+
105+
cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]
106+
107+
return cell
108+
}
109+
```
110+
111+
And here is the toggle function:
112+
113+
```swift
114+
func toggleCollapse(sender: UIButton) {
115+
let section = sender.tag
116+
let collapsed = sections[section].collapsed
117+
118+
// Toggle collapse
119+
sections[section].collapsed = !collapsed
120+
121+
// Reload section
122+
tableView.reloadSections(NSIndexSet(index: section), withRowAnimation: .Automatic)
123+
}
124+
```
125+
126+
That's it, please refer to the source code and see the detailed implementation.

0 commit comments

Comments
 (0)