Nate
Nate

Reputation: 33

Auto Re-Sizing Tableview cell to the cells content (SWIFT)

I'm trying to get my tableview to work so when a cell is clicked it resizes to fit the content inside the cell automatically. (Different amounts of text will automatically re-size different.

Cell when not clicked (first state and size it should go back to when clicked = 44.0

So with this image, this is the stage each cell will be in only as default and deselected. The white text will be the only thing visible.

Cell clicked state. resizes to my "let selectedCellHeight: CGFloat = 88.0 " constant. Which needs to automatically size to fit the green text no matter how much is in there.

This is my full code for the tableview and viewcontroller.

import UIKit

class TasksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var tblTasks: UITableView!

//For persisting data
let defaults = UserDefaults.standard


override func viewDidLoad() {
    super.viewDidLoad()



    self.tblTasks.backgroundColor = UIColor(red: 64/255.0, green: 67/255.0, blue: 68/255.0, alpha: 0)


    self.tblTasks.reloadData()
    self.tblTasks.register(UINib(nibName: "WhiteTaskTableViewCell", bundle: nil), forCellReuseIdentifier: "nameCell")
    tblTasks.tableFooterView = UIView()

    let darkModeColor = UIColor(red: 52/255.0, green: 55/255.0, blue: 55/255.0, alpha: 1.0)
    view.backgroundColor = darkModeColor


    tblTasks.dataSource = self;

    // Do any additional setup after loading the view.
}



override func viewWillAppear(_ animated: Bool) {
    self.tblTasks.reloadData()
}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    return taskMgr.tasks.count

}



//Define how our cells look - 2 lines a heading and a subtitle
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{


    let identifier = "nameCell"
    var cell: WhiteTaskTableViewCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? WhiteTaskTableViewCell

    if cell == nil {
        tableView.register(UINib(nibName: "WhiteTaskTableViewCell", bundle: nil), forCellReuseIdentifier: identifier)
        cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? WhiteTaskTableViewCell
    }


    //        Assign the contents of our var "items" to the textLabel of each cell
    //        cell.textLabel!.text = taskMgr.tasks[indexPath.row].name
    //        cell.detailTextLabel!.text = taskMgr.tasks[indexPath.row].desc

    cell.TaskNameLabel.text = taskMgr.tasks[indexPath.row].name
    cell.NotesLabel.text = taskMgr.tasks[indexPath.row].note

    cell.selectionStyle = .none



    return cell

}



func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
}



   func tableView(_ willDisplayforRowAttableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.backgroundColor = UIColor(red: 64/255.0, green: 67/255.0, blue: 68/255.0, alpha: 0)
}



func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == UITableViewCellEditingStyle.delete) {
        // handle delete (by removing the data from your array and updating the tableview)

        taskMgr.removeTask(indexPath.row)
        tblTasks.reloadData()
    }
}



   // EXPAND CELL ON CLICK


// Global Variables/Constants

var selectedCellIndexPath: NSIndexPath?

let selectedCellHeight: CGFloat = 88.0
let unselectedCellHeight: CGFloat = 44.0

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

    self.tblTasks.rowHeight = UITableViewAutomaticDimension

    if selectedCellIndexPath == indexPath as NSIndexPath?  {
        return selectedCellHeight
    }
    return unselectedCellHeight
}



 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if selectedCellIndexPath != nil && selectedCellIndexPath == indexPath as NSIndexPath? {
        selectedCellIndexPath = nil
    } else {
        selectedCellIndexPath = indexPath as NSIndexPath?
    }

    tableView.beginUpdates()
    tableView.endUpdates()

    if selectedCellIndexPath != nil {
        // This ensures, that the cell is fully visible once expanded
        tableView.scrollToRow(at: indexPath as IndexPath, at: .none, animated: true)
    }
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/


}

I'm open to any help and insight. Thank you very much.

Upvotes: 3

Views: 2868

Answers (1)

David Seek
David Seek

Reputation: 17152

You need to set an Outlet to your UITableView and set the rowHeight parameter to UITableViewAutomaticDimension. Also you need set the estimatedRowHeight to a value fitting your needs. This way the size of the Cell will fit the size of its content.

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
      super.viewDidLoad()        
      tableView.estimatedRowHeight = 55
      tableView.rowHeight = UITableViewAutomaticDimension
}

For this to work, you need to set the Autolayout Constraints for every element of your Cell.

Source Apple Doc:

enter image description here

Working with Self-Sizing Table View Cells

In iOS, you can use Auto Layout to define the height of a table view cell; however, the feature is not enabled by default.

Normally, a cell’s height is determined by the table view delegate’s tableView:heightForRowAtIndexPath: method. To enable self-sizing table view cells, you must set the table view’s rowHeight property to UITableViewAutomaticDimension. You must also assign a value to the estimatedRowHeight property. As soon as both of these properties are set, the system uses Auto Layout to calculate the row’s actual height.

Additionally, try to make the estimated row height as accurate as possible. The system calculates items such as the scroll bar heights based on these estimates. The more accurate the estimates, the more seamless the user experience becomes.

enter image description here

Upvotes: 3

Related Questions