Expandable and dynamic sized Table View Cell

A quick look at how to dynamically expand and resize a table view cell without having to reload it.

Thomas Asheim Smedmann
3 min readAug 9, 2022
Expandable and dynamic sized Table View Cell.

The Pokémon images and facts in the gif are “borrowed” from the awesome website https://pokemondb.net/. Check it out for more awesome Pokémon stuff 🙌

Table views are awesome, and might be one of the most used UIKit subviews. Even though it’s easy to refresh the content of a single (or multiple) cells by calling methods like UITableView.reloadRows(at:with:), its not always what you desire. Sometimes you just want to update the layout of a cell without having to implicitly invoke any of the UITableView’s delegate methods (like UITableViewDataSource.tableView(_:cellForRowAt:)).

Fear not! By wrapping your wanted layout changes in a call to UITableView.performBatchUpdates(_:completion:) you can achieve just this.

This is even stated in the documentation of the UITableView.beginUpdates() as follows: “You can also use this method followed by the endUpdates() method to animate the change in the row heights without reloading the cell”. This method is an alternative to UITableView.performBatchUpdates(_:completion:), but the latter is the preferred one.

Key takeaways

  • By applying layout changes to one or more UITableViewCell in a call to UITableView.performBatchUpdates(_:completion:), the UITableView will detect the changes and automatically resize the cell(s).
  • Your layout changes to a cell can also optionally be animated, though you will have to set up the animations manually (e.g. by calling UIView.animate(withDuration:animations:)). The UITableView will always use a default animation when resizing a cell, and this animation can not be changed in any way. So a good tip is to time your animations to match the timing of the UITableView’s default animation.
  • To orchestrate the layout update of a cell that wants to change its layout, you would either let the cell grab a hold on to its parent UITableView (and manage the calls to UITableView.performBatchUpdates(_:completion:) by itself), or use a delegate (or some other way of communication) to let the world know that the cell wants to update its layout.

Examples

Accordion

A simple accordion using expandable table view cells (AccordionTableViewCell).

AccordionTableViewCell.swift

In this example the table view cell (AccordionTableViewCell) has a delegate (ExpandableTableViewCellDelegate) that is used to tell anyone of interest that a cell just changed its layout. This is useful in order to track wich of the accordion rows is currently expanded/collapsed. Otherwise this information might be lost if — for example — the user scroll too far and the cell is recycled.

Other than that, the cell is itself is responsible for applying layout updates to it self between calls to UITableView.beginUpdates() and UITableView.endUpdates() on its parent UITableView.

Note: I’ve used UITableView.beginUpdates() and UITableView.endUpdates() in this example, but the preferred way is to use UITableView.performBatchUpdates(_:completion:).

Expandable details

Expandable — and animated — details list, using expandable table view cells (DetailsTableViewCell).

DetailsTableViewCell.swift

Here the cell (DetailsTableViewCell) delegate the responsebility to change its layout to the outside world. This could be via a custom delegate or — like in this example — by acting when the UITableView’s delegate UITableViewDelegate.tableView(_:didSelectRowAt:) method is called.

In the delegate method, layout changes to the cell is applied in between calls to UITableView.beginUpdates() and UITableView.endUpdates(). The delegate method also makes sure to take note of which cells that are expanded or not.

Note: I’ve used UITableView.beginUpdates() and UITableView.endUpdates() in this example, but the preferred way is to use UITableView.performBatchUpdates(_:completion:).

That’s it!

Hopefully this article has provided some useful insight on how to create a table view cell that dynamically changes its content size without needing to have the table view reload the cell.

Happy coding! 🙌

--

--