Antonio A. Chavez
Antonio A. Chavez

Reputation: 1026

How to make Expandable with only Cells (NOT SECTION/ HEADER) with UITableView in Swift?

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!

Upvotes: 0

Views: 855

Answers (1)

DonMag
DonMag

Reputation: 77423

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
        
        // if it's the first row in a section,
        //  show accessoryView with
        //      chevron.up or chevron.down
        //  based on section Object expanded property
        if indexPath.row == 0 {
            let chevronName = objectArray[indexPath.section].expanded ? "chevron.up" : "chevron.down"
            let img = UIImage(systemName: chevronName)
            let disclosureView = UIImageView(image: img)
            cell.accessoryView = disclosureView
        } else {
            // not the first row in a section, so
            //  clear the accessoryView
            cell.accessoryView = nil
        }
    
        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
        }
    }
    
}

Upvotes: 1

Related Questions