I researched all StackOverflow about Expandable Table View, but they have posted only a show header with the cells. In fact that iOS 15 has changed the new design interfaces of the UITableView as known .insetGrouped
.
Basically Header in .insetGrouped
really terrible design interfaces for Expandable. I am trying to get my idea to use only cell to do Expandable without section needed.
My Table View codes Here:
class HelpViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
struct Object {
var seactionName: String!
var seactionObjection: [String]!
var footerName: String!
}
var objectArray = [Object]()
var TableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
objectArray = [
Object(seactionName: "Header", seactionObjection: ["Expandable Cell", "One Row", "Two Row"],
footerName: "Footer"),
// copy and paste new cells
]
title = "Help Center"
view.backgroundColor = UIColor.quaternarySystemFill
TableView.frame = view.bounds
TableView = UITableView(frame: self.view.bounds, style: UITableView.Style.insetGrouped)
TableView.showsVerticalScrollIndicator = true
TableView.indicatorStyle = .default
TableView.register(SliceCell.self, forCellReuseIdentifier: "Slice List")
TableView.delegate = self
TableView.dataSource = self
view.addSubview(TableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objectArray[section].seactionObjection.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return objectArray.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return objectArray[section].seactionName
}
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return objectArray[section].footerName
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Slice List") as! SliceCell
cell.backgroundColor = .secondarySystemGroupedBackground
cell.textLabel?.text = objectArray[indexPath.section].seactionObjection[indexPath.row]
cell.textLabel?.numberOfLines = 0
return cell
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
view.tintColor = .clear
let header = view as! UITableViewHeaderFooterView
header.textLabel?.textColor = UIColor.label
}
}
Well, I could change this code
cell.accessoryType = .disclosureIndicator
to this
let disclosureIndicatorTapped = UIImageView()
disclosureIndicatorTapped.image = UIImage(systemName: "chevron.forward") // When tapped automatic to "Chevron.down"
cell.accessoryView = disclosureIndicatorTapped
Any idea how to get Expandable Cells in UITableView with Swift, without Header or Footer needed?
Thanks!
CodePudding user response:
You can add a Bool "expanded" property to your Object.
In numberOfRowsInSection
, if expanded is True, return the count of items in seactionObjection
, else return 1
.
Then, in didSelectRowAt
, if it's the first row in a section, toggle the expanded
property of that section's Object, and reload the section.
Here's a modified version of your controller class:
class HelpViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
struct Object {
var seactionName: String!
var expanded: Bool!
var seactionObjection: [String]!
var footerName: String!
}
var objectArray = [Object]()
var TableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
objectArray = [
Object(seactionName: "Header 1",
expanded: false,
seactionObjection: ["Expandable Cell 1", "One Row 1", "Two Row 1"],
footerName: "Footer 1"),
Object(seactionName: "Header 2",
expanded: false,
seactionObjection: ["Expandable Cell 2", "One Row 2", "Two Row 2"],
footerName: "Footer 2"),
Object(seactionName: "Header 3",
expanded: false,
seactionObjection: ["Expandable Cell 3", "One Row 3", "Two Row 3"],
footerName: "Footer 3"),
// copy and paste new cells
]
title = "Help Center"
view.backgroundColor = UIColor.quaternarySystemFill
TableView.frame = view.bounds
TableView = UITableView(frame: self.view.bounds, style: UITableView.Style.insetGrouped)
TableView.showsVerticalScrollIndicator = true
TableView.indicatorStyle = .default
TableView.register(SliceCell.self, forCellReuseIdentifier: "Slice List")
TableView.delegate = self
TableView.dataSource = self
view.addSubview(TableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// if section is expanded
// return count of seactionObjection
// else
// return 1
return objectArray[section].expanded ? objectArray[section].seactionObjection.count : 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return objectArray.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return objectArray[section].seactionName
}
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return objectArray[section].footerName
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Slice List") as! SliceCell
cell.backgroundColor = .secondarySystemGroupedBackground
cell.textLabel?.text = objectArray[indexPath.section].seactionObjection[indexPath.row]
cell.textLabel?.numberOfLines = 0
return cell
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int){
view.tintColor = .clear
let header = view as! UITableViewHeaderFooterView
header.textLabel?.textColor = UIColor.label
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
objectArray[indexPath.section].expanded.toggle()
tableView.reloadSections([indexPath.section], with: .automatic)
} else {
// do something else on row selection
}
}
}