Anoop Kumar
Anoop Kumar

Reputation: 11

If one section is expanded then all the other sections should be collapsed in table view in Swift 5. How should I implement this

import UIKit

//MARK: - Model struct MobileModel { var brand: String? var isExpanded = false var model: [String]? }

class ViewController: UIViewController {

@IBOutlet weak var productInfoTableView: UITableView!
private var mobileDataArray = [MobileModel]()
private var isSelected = false

//MARK: - Life Cycle
override func viewDidLoad() {
    super.viewDidLoad()
    //MARK: - Data
    mobileDataArray = [MobileModel(brand: "Nokia", model: ["Nokia 1","Nokia 6.1","Nokia 10","Nokia 8.5"]),
    MobileModel(brand: "Mi", model: ["Redmi Note 4","Redmi Note 5","Redmi Note 5 Pro","Redmi Note 6","Redmi 5","Redmi Note 10"]),
    MobileModel(brand: "Samsung", model: ["Samsung Galaxy S8","Samsung M20","Samsung A50","Samsung Champ"]),
    MobileModel(brand: "Apple", model: ["iPhone 6s","iPhone 8","iPhone 10","iPhone 10 Pro","iPhone 7"])]
}

}

//MARK: - Table View Delegates extension ViewController: UITableViewDataSource, UITableViewDelegate {

//MARK: - No of Sections
func numberOfSections(in tableView: UITableView) -> Int {
    return mobileDataArray.count
}

//MARK: - No of cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if self.mobileDataArray[section].isExpanded {
        return mobileDataArray[section].model?.count ?? 0
    } else {
        return 0
    }
}

//MARK: - Cell Items
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = mobileDataArray[indexPath.section].model?[indexPath.row]
        return cell
}

//MARK: - Section Header
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 40))
    view.backgroundColor = .cyan
    let btn = UIButton(type: .system)
    btn.setTitle(mobileDataArray[section].brand, for: .normal)
    btn.titleColor(for: .normal)
    btn.tag = section
    btn.frame = view.bounds
    btn.addTarget(self, action: #selector(selectHeader(sender:)), for: .touchUpInside)
    //let lbl = UILabel(frame: CGRect(x: 15, y: 0, width: view.frame.width - 15, height: 40))
    //lbl.text = mobileData[section].brand
    view.addSubview(btn)
    return view
}

@objc func selectHeader(sender: UIButton) {
    if isSelected {
        self.mobileDataArray[sender.tag].isExpanded = !self.mobileDataArray[sender.tag].isExpanded
        self.productInfoTableView.reloadSections([sender.tag], with: .fade)
    } else {
        self.mobileDataArray[sender.tag].isExpanded = true
    }
}

}

Upvotes: 0

Views: 639

Answers (2)

sikandar patel
sikandar patel

Reputation: 1

For the DiffableDataSource we can archive using the sectionSnapshotHandlers here is an example

dataSource.sectionSnapshotHandlers.shouldExpandItem = self.checkAndHideOtherItems(_:)

func checkAndHideOtherItems(_ item: FAQListItem) -> Bool {
        var snap = self.dataSource.snapshot(for: FAQSection.main)
        snap.collapse(sectionSnapshot.rootItems)
        self.dataSource.apply(snap,to: .main,animatingDifferences: false)
        return true
    }

In this example, we collapse all the headers and return true for the current header so only the current header will expanded

Upvotes: 0

Adli R
Adli R

Reputation: 71

Edited:

implement this and see how its work

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == self.selectedIndex {
    return mobileDataArray[section].model?.count ?? 0
} else {
    return 0
}
}

explaination:

since i cant debug your code, maybe there is some isExpanded variable at index X doesn't changed.

by doing adjustment condition as above , at least only 1 index section is same.

if you have concern about the animation if you already use tableView.reloadData()

just use this instead:

@objc func selectHeader(sender: UIButton) {
if isSelected {
    self.mobileDataArray[sender.tag].isExpanded = !self.mobileDataArray[sender.tag].isExpanded

    UIView.animate(withDuration: 0.5) {
    tableView.beginUpdates()
    tableView.reloadData()
        self.view.layoutIfNeeded()
    tableView.endUpdates()

    }
} else {
    self.mobileDataArray[sender.tag].isExpanded = true
}

}

note : i'm not using compiler so there will be grammatical error

Upvotes: 1

Related Questions