You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A simple iOS swift project demonstrates how to implement collapsible table section programmatically, that is no main storyboard, no XIB, no need to register nib, just purley Swift!
5
4
6
-
### Coming Soon ###
7
-
- Use `UITableViewHeaderFooterView` instead of `UITableViewCell` according to [Apple API reference](https://developer.apple.com/reference/uikit/uitableviewheaderfooterview).
### How to implement collapsible table sections? ###
15
12
@@ -40,37 +37,104 @@ sections = [
40
37
```
41
38
`collapsed` indicates whether the current section is collapsed or not, by default is `false`.
42
39
43
-
#### Step 2. Design the Header and Cell ####
40
+
#### Step 2. The Section Header ####
44
41
45
-
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.
42
+
According to [Apple API reference](https://developer.apple.com/reference/uikit/uitableviewheaderfooterview), we should use `UITableViewHeaderFooterView`. Let's subclass it and implement the section header`CollapsibleTableViewHeader`:
46
43
47
-
<br />
48
-
49
-
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.
fatalError("init(coder:) has not been implemented")
58
+
}
59
+
}
60
+
```
50
61
51
-
Now the file should look like this:
62
+
We need to collapse or expand the section when user taps on the header, to achieve this, let's borrow `UITapGestureRecognizer`. Also we need to delegate this event to the table view to update the `collapsed` property.
// Animate the arrow rotation (see Extensions.swf)
88
+
arrowLabel.rotate(collapsed ?0.0:CGFloat(M_PI_2))
89
+
}
61
90
}
62
91
```
63
92
64
-
By creating a prototype cell and subclassing UITableViewCell, we have the following benefits:
65
-
* We can visually design the custom header
66
-
* We shouldn't need to create a nib and register it to the the tableView like so:
93
+
Since we are not using any storyboard or XIB, how to do auto layout programmatically? The answer is `NSLayoutConstraint`'s `constraintsWithVisualFormat` function.
94
+
67
95
```swift
68
-
let nib =UINib(nibName: "TableSectionHeader", bundle: nil)
personally I don't like having nibs in my project and if we use `dequeueReusableHeaderFooterViewWithIdentifier`, seems like we must have at least 1 row in that section, but we need to have 0 row!
72
136
73
-
#### Step 3. The UITableViewDelegate ####
137
+
#### Step 3. The UITableView DataSource and Delegate ####
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:
#### Step 4. How to Toggle Collapse and Expand ####
185
+
186
+
The idea is really simple, if a section's `collapsed` property is `true`, we set the height of the rows inside that section to be `0`, otherwise `44.0`!
// Adjust the height of the rows inside the section
206
+
tableView.beginUpdates()
207
+
for i in0..< sections[section].items.count {
208
+
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: i, inSection: section)], withRowAnimation: .Automatic)
209
+
}
210
+
tableView.endUpdates()
211
+
}
133
212
}
134
213
```
135
214
215
+
Noticed that we don't lazily just reload the whole section, we only reload the rows inside that section, so that we won't see the refresh of the section header, and most importantly it will allow us to animate anything in the section header smoothly, i.e., rotate the arrow label, change the background etc.
216
+
136
217
That's it, please refer to the source code and see the detailed implementation.
0 commit comments