Expand and Contract Tableview Cell When Tapped, in Swift

Expand and contract tableview cell when tapped, in swift

You need to take in account that you need to update your selected row when another is tapped, see the following code :

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

if indexPath.row == selectedRowIndex {
return 140
}
return 44
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

if selectedRowIndex != indexPath.row {

// paint the last cell tapped to white again
self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: self.selectedRowIndex, inSection: 0))?.backgroundColor = UIColor.whiteColor()

// save the selected index
self.selectedRowIndex = indexPath.row

// paint the selected cell to gray
self.tableView.cellForRowAtIndexPath(indexPath)?.backgroundColor = UIColor.grayColor()

// update the height for all the cells
self.tableView.beginUpdates()
self.tableView.endUpdates()
}
}

EDIT:

To handle that the cell where is selected and is tapped again return to its original state you need to check some conditions like the following:

var thereIsCellTapped = false
var selectedRowIndex = -1

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {

if indexPath.row == selectedRowIndex && thereIsCellTapped {
return 140
}

return 44
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

self.tableView.cellForRowAtIndexPath(indexPath)?.backgroundColor = UIColor.grayColor()

// avoid paint the cell is the index is outside the bounds
if self.selectedRowIndex != -1 {
self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: self.selectedRowIndex, inSection: 0))?.backgroundColor = UIColor.whiteColor()
}

if selectedRowIndex != indexPath.row {
self.thereIsCellTapped = true
self.selectedRowIndex = indexPath.row
}
else {
// there is no cell selected anymore
self.thereIsCellTapped = false
self.selectedRowIndex = -1
}

self.tableView.beginUpdates()
self.tableView.endUpdates()
}

With the above modifications in yourdidSelectRowAtIndexPath and heightForRowAtIndexPath functions you can see when a cell is tapped its background color it will be changed to gray when it's height grow and when another cell is tapped the cell is painted to white and the tapped to gray and again and again allowing only tap one cell at time.

I though you can benefit and learn how to do a Accordion Menu in this repo I have created and I plan to update very soon to handle better results, it's handle using a UITableView just like you want.

Any doubt in the repository you can post it here.

I hope this help you.

Expand cell when tapped in Swift

The first comparison in your if statement can never be true because you're comparing an indexPath to an integer. You should also initialize the selectedRowIndex variable with a row value that can't be in the table, like -1, so nothing will be expanded when the table first loads.

var selectedRowIndex: NSIndexPath = NSIndexPath(forRow: -1, inSection: 0)

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == selectedRowIndex.row {
return 100
}
return 70
}

Swift 4.2 var selectedRowIndex: NSIndexPath = NSIndexPath(row: -1, section: 0)

(Swift) Expand and Collapse tableview cell when tapped

You can do that but you need to do some coding. First of all detect when a row is selected (keep the Index Path of the selected row in a variable). When a row is selected you will add the index path of the new selected row and that of the previously selected (that you have in the variable) in an array that you pass to the tableView reloadRows from inside didSelectRowAt, this function will force redrawing of the two rows and the heightForRowAt function will be called to get the height of both rows, in heightForRowAt you will check the currently selected row (do you remember the variable I mentioned earlier?) and return the expanded height for that, while for the others you return the collapsed height. You should get the result you want. Hope that will help.

How to reload selected cell in particular section for expand/collapse in tableview Swift

If you store section and row independently in separate arrays, your algorithm will fail.
The reason is that both are dependent:
Think of three expanded cells (row:1, section:1), (row:2, section:1), (row:3, section:2)

Now what happens for the cell (row:3, section:1)?
The row-array contains the value "3", and the section-array contains value "1", therefore it will be considered as expanded.

Therefore, you need to store the index path as a whole - see the sample code:

var expanded:[IndexPath] = []

expanded.append(IndexPath(row:1, section:1))
expanded.append(IndexPath(row:2, section:1))
expanded.append(IndexPath(row:3, section:2))

let checkPath = IndexPath(row:3, section:1)
if (expanded.contains(checkPath)) {
print ("is expanded")
} else {
print ("collapsed")
}

Update

So in your button handle, you'll do the following:

@IBAction moreButtonTapped(_ sender: Any) {

if(expanded.contains(indexPath)) {
expanded.removeAll { (checkPath) -> Bool in
return checkPath == indexPath
}
} else {
expanded.append(indexPath)
}
entriesTableView.beginUpdates()
entriesTableView.reloadRows(at: [indexPath], with: .none)
entriesTableView.endUpdates()
}

Expand the only tapped cell and collapse other cells

You need to collapse all cells and change the current clicked one state , then reload all the table

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let current = datasource[indexPath.row].expanded
datasource.forEach { $0.expanded = false }
let content = datasource[indexPath.row]
content.expanded = !current
tableView.reloadData()
}

Unable to Expand and Collapse TableViewCell in Swift

Add a property to your activeCategories array 's model

var isExpanded = true

Then inside numberOfRowsInSection

guard let item = self.activeCategories?[section] else { return 0 }
return item.isExpanded ? (item.sub_categories?.count ?? 0) : 0

Then play with isExpanded and refresh the table

Edit

Inside viewForHeaderInSection

 let header = tableView.dequeueReusableCell(withIdentifier: "CategoryTableCell") as! CategoryTableCell 
button.tag = section

Then inside action

@objc headerClicked(_ sender:UIButton) {
let section = sender.tag
guard let item = self.activeCategories?[section] else { return 0 }
item.isExpanded.toggle()
tableView.reloadData()
}


Related Topics



Leave a reply



Submit