I have Implemented Tableview in swift, but I want to Make Expandable TableView Please Give the idea..
This the code for Tableview..
//MARK: - TableView Delegate and Datasource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return MenuNameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MenuTableViewCell", for: indexPath) as! MenuTableViewCell
cell.menuNameLabel.text = NameArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
Here You Go , Try This Out : -
struct ExpandableNames {
var isExpanded : Bool
var names : [String]
}
struct Contact {
let names : String
}
in your Class - >
var twoDArray = [
ExpandableNames(isExpanded : true,names:["Krishna","Rishabh","Aditya","Chandan","Nipun","Navdeesh","Steve"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:["Carl","Michal","Tommy","Jennny","Vikram","Swati"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:["David","dude","dfff","dcc","daa","dee","dsss"].map
{
Contact(names: $0)
}),
ExpandableNames(isExpanded : true,names:[Contact(names: "Pattrick", hasFav: false)])
]
let cellId = "cellID"
let identifier = "attachmentCellID"
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
return 50
}
func numberOfSections(in tableView: UITableView) -> Int
{
return twoDArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if !twoDArray[section].isExpanded
{
return 0
}
return twoDArray[section].names.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let btn = UIButton(type: .system)
if(section == 0)
{
btn.setTitle("Tap To View Classes", for: .normal)
}
else if(section == 1)
{
btn.setTitle("Tap To View Admins", for: .normal)
}
btn.setTitleColor(.black, for: .normal)
btn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
btn.addTarget(self, action: #selector(handleExpandClose), for: .touchUpInside)
btn.backgroundColor = AppColors.greyBorderColor
btn.tag = section
return btn
}
@objc func handleExpandClose(button : UIButton)
{
let section = button.tag
var indexPaths = [IndexPath]()
for row in twoDArray[section].names.indices
{
let indexPath = IndexPath(row: row, section: section)
indexPaths.append(indexPath)
}
let isExpanded = twoDArray[section].isExpanded
twoDArray[section].isExpanded = !isExpanded
button.setTitle(isExpanded ? "Tap To View Classes" : "Classes", for: .normal)
if isExpanded
{
tableView.deleteRows(at: indexPaths, with: .fade)
}
else
{
tableView.insertRows(at: indexPaths, with: .fade)
}
}
And Rest in cellForRowAt -
let contact = twoDArray[indexPath.section].names[indexPath.row]
cell.textLabel?.text = contact.names
First you will need a model defining if the cell is open, for example, an array of indexPaths:
var openPaths = [IndexPath]()
now when select the cell you toggle wether it is open or not and reload the cell
if let index = openPaths.index(indexPath) {
openPaths.remove(atIndex: index)
} else {
openPaths.append(indexPath)
}
tableView.beginUpdates()
tableView.reloadRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
Now in your cell setup, use a stackview, and in the cell config, you hide the expandable part based on if the cells indexPath is in openPaths
Use heightForRowAt
delegate method to change height of cell:-
Add a boolean property to your object say isExpanded, change the value in
didSelectRowAt
delegate by
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
YourModel[indexPath.row].isExpanded = !YourModel[indexPath.row].isExpanded
tableView.reloadRows(at: [indexPath], with: Animation)
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if YourModel[indexPath.row].isExpanded {
return 200
} else {
return 50
}
}