Lawrence Gimenez

Implementing the expandable cell in iOS UITableView

I’m going to implement below on how to create the expandable UITableView cell for example on iOS stock calendar.

1-K0Xsn4n9Lx2lqpUDNO-xXA

From scratch, create a new project on Xcode. In your main.storyboard remove the default ViewController (delete also the extra unused ViewController.swift file in the project explorer) and drag a new TableViewController.

1-ti0Kq9gWuhSdxOPXvRjDDw

Now that we have our TableViewController set on the storyboard. Let’s create a new Swift file, and call it for example FormTableViewController.swift. And set is as the custom class in your TableViewController.

1-XPDBMIMfwL7hBdvehkUnjQ
1-366I_Aw3939Z5uXtdVX0fg

Now we are all set. We are gonna change the TableView’s Content from Dynamic Prototypes to Static Cells.

After setting it to Static Cells, your TableView will have a default of 3 static cells created.

For this demo it won’t matter how many cells we are going to use.

The secret to this is the proper measurement of a cell. Click on the first cell and change the row height to 250. Our plan is, inside the cell we will have 2 views. The Label which has a height of 50 and DatePicker with a height of 200. A total of 250. On the storyboard, drag a Label and DatePicker on the first cell, setup its constraints and embed our TableViewController with a NavigationController, it should look like the image below.

1-VOvLjMRH2f8Gyu7LmfFvYA

Now let’s start coding. Inside your FormTableViewController you need to override two functions, namely TableView’s didSelectRowAt and heightForRowAt.

import UIKit

class FormTableViewController: UITableViewController {

    private var dateCellExpanded: Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // For removing the extra empty spaces of TableView below
        tableView.tableFooterView = UIView()
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row == 0 {
            if dateCellExpanded {
                dateCellExpanded = false
            } else {
                dateCellExpanded = true
            }
            tableView.beginUpdates()
            tableView.endUpdates()
        }
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if indexPath.row == 0 {
            if dateCellExpanded {
                return 250
            } else {
                return 50
            }
        }
        return 50
    }
}

I’m going to explain shortly about the code. The variable dateCellExpanded is a flag to determine if the current cell selected has been expanded or not. Then, after always call tableView.beginUpdates() and tableView.endUpdates() and it will trigger the delegate function of TableView heightForRowAt to determine what height value should we return or not. Yep, it is that simple. Click RUN!

1-_TMKiaY6yEn4iGw2w_vdvQ

Hopefully this demo should give you an idea on how to implement it on your app.

The example project can be found at https://github.com/lawgimenez/expandable-cell-test