SANTOSH
SANTOSH

Reputation: 183

Expandable Tableview work with sectionHeader

I am trying to load my different controller using Expandable Tableview but my headerview is set as switch condition

For Header XXX1 -> two sub menu a and b .. For Header XXX2-> sub menu c but for Header XXX3 no sub menu ,, So i will work on click with XXX3(currently working with check SectionData.count == 0 ) but for multiple how to manage .. check out my code

 sectionNames = ["xxxx1","xxxx2","xxx3","xxxx4"] //this is main header
 sectionItems = [ ["a","b"],[c],[],[],[],[],[],[]]// This is sub menu items

   func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if (self.expandedSectionHeaderNumber == section) {
            let arrayOfItems = self.sectionItems[section] as! NSArray
            return arrayOfItems.count;
        } else {
            return 0;
        }
        //return arraylist.count
    }


    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if (self.sectionNames.count != 0) {
            return self.sectionNames[section] as? String
        }
        return ""
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 60.0;
    }

    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 50))
        return footerView
    }

    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 0.5

    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifer, for: indexPath)
        let section = self.sectionItems[indexPath.section] as! NSArray
        cell.textLabel?.textColor = UIColor.black
        cell.textLabel?.text = section[indexPath.row] as? String
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        if indexPath.row == 0 {

        }


        let indexPath = tableView.indexPathForSelectedRow
        //  print(indexPath as Any)

        //getting the current cell from the index path
        let currentCell = tableView.cellForRow(at: indexPath!)! as UITableViewCell
        //   print(currentCell as Any)

        //getting the text of that cell
        let currentItem = currentCell.textLabel!.text
        print(currentItem!)

        switch currentItem { 
          case "XXXX1":
            //// Here unable to do any work
            break
          case "a":
            APICalla()
          case "b":
            APICallb ()
          default:
            break
        }
        return
    }

Using this link

Upvotes: 0

Views: 115

Answers (2)

Sukh
Sukh

Reputation: 1398

Swift4 I think this will helps you

// declare globally
   var isExpanded : Bool = true
   var indexOfSection = Int()
   var yourArray = [ModelName]()
 override func viewDidLoad() {
        super.viewDidLoad()
        indexOfSection = 999
    }
extension ViewController: UITableViewDelegate, UITableViewDataSource
{
    func numberOfSections(in tableView: UITableView) -> Int {
            if yourArray.count > 0{
                return yourArray.count
            }else{
                return 0

        }

    }
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let headerView = UIView(frame: CGRect(x: view.frame.origin.x,y: 0 , width: view.frame.size.width ,height: 60))
        headerView.backgroundColor = .white
        let collapseBtn = UIButton(frame: CGRect(x: headerView.frame.origin.x,y: headerView.frame.origin.y , width: view.frame.size.width ,height: 60))
        collapseBtn.addTarget(self, action: #selector(expandSection(sender:)), for: .touchUpInside)
        collapseBtn.tag = section
        collapseBtn.backgroundColor = .clear
        headerView.addSubview(collapseBtn)

        return headerView
    }

    @objc func expandSection(sender:UIButton){
        print(sender.tag)
        if isExpanded == true{
            indexOfSection = sender.tag
            mIdeaTableView.reloadData()
            isExpanded = false
            mTableView.reloadSections([indexOfSection], with: UITableView.RowAnimation.bottom)
        }else{
            indexOfSection = 999
            isExpanded = true
            self.mTableView.reloadData()

        }
    }


    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
            return 60

    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

            if yourArray.count > 0{
                if yourArray[section].items!.count > 0{
                    if indexOfSection == section{
                        return yourArray[section].items!.count
                    }else{
                        return 0
                    }
                }else{
                    return 0
                }
            }else{
                return 0
            }

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let cell = tableView.dequeueReusableCell(withIdentifier: “CellID”, for: indexPath) as! Cell
            if yourArray[indexPath.section]. items!.count > 0{
                if yourArray[indexPath.section]. items!.count > 0{
                    let ideas = yourArray[indexPath.section].ideaItems
                    if ideas!.count > 0{
                        if indexOfSection == indexPath.section{
                            cell.mLbl.text = ideas![indexPath.row].name ?? ""
                            if ideas![indexPath.row].isExpanded == true{
                                cell.mAddImg.image = #imageLiteral(resourceName: "tick")
                            }else{
                                cell.mAddImg.image = #imageLiteral(resourceName: "edit213-1")
                            }
                        }
                    }
                }


            }

            return cell

    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                return 60
    }
 }

//Structure of my response 
{
            items =             (
                                {
                    name = “a”;
                },
                                {
                    name = “b”;
                },
                                      );
            name = “xxxx1”;
        }
            items =             (
                                {
                    name = “c”;
                },
                                      );
            name = “xxxx2”;
        }

}

Upvotes: 0

vadian
vadian

Reputation: 285064

Sorry this tutorial is quite poor.

Swift is an object oriented language so use a custom model, a generic Section object with name, items and the information if the section is collapsed

class Section<T> {
    var name : String
    var items = [T]()

    var isCollapsed = false

    init(name : String, items : [T] = []) {
        self.name = name
        self.items = items
    }
}

and a suitable struct for the items with a title and a closure to be called in didSelect

struct Item {
    let title : String
    let selectorClosure : (() -> Void)?
}

Rather than using multiple arrays populate the data source array consistently

var sections = [Section<Item>(name:"xxxx1", items: [Item(title: "a", selectorClosure: APICalla), Item(title: "b", selectorClosure: APICallb)]),
                Section<Item>(name:"xxxx2", items: [Item(title: "c", selectorClosure: APICallc)]),
                Section<Item>(name:"xxxx3")]

In numberOfRowsInSection return the proper number of items depending on isCollapsed

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let currentSection = sections[section]
    return (currentSection.isCollapsed) ? 0 : currentSection.items.count
}

In cellForRow don't use typeless Foundation collection types

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifer, for: indexPath)
    let item = sections[indexPath.section].items[indexPath.row]
    cell.textLabel?.textColor = UIColor.black
    cell.textLabel?.text = item.title
    return cell
}

In the method to collapse/expand the sections just toggle isCollapsed

let currentSection = sections[section]
currentSection.isCollapsed.toggle()

and perform the animation


titleForHeaderInSection is much simpler, too

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
   return sections[section].name
}

In didSelectRow never get any data from the view (the cell) get it from the model (the data source array) and call the selector closure. With this logic a switch is not needed.

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: false)
    let item = sections[indexPath.section].items[indexPath.row]
    item.selectorClosure?()
}

Upvotes: 1

Related Questions