I have a UITableView that holds cells that can show video, html, and images, and a UI of audio playback. That's effectively 3 different cells that could potentially be in the tableView in any given point in time. Cells of the same type can have different heights. That's the problem I'm trying to solve. Out of all the tutorials I've watched/read through, none taught me how to set the calculate then set the heights dynamically. I've only read stuff that show you how to tableViews with different cells that have static heights. Any suggestions on how to solve this problem?
Apply auto-layout in table view cell for cell-items and bound it with both top and bottom and use estimatedHeightForRowAt as:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Or you can manually set the height for different rows as:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50 // rather than 50 return height you need to set
}
Related
I have a UITableView cell with a stack view inside. When the cell is tapped the data source changes and the table view is reloaded. The stack view will now have more views inside and the cell is bigger. However sometimes when I scroll the table there is jerky behaviour. It's almost like the cell size was calculated wrong or something (even though it looks fine). Once the tableview has jerked once it is fine and doesn't do it again until I tap the cell and it adds more stack views.
I am using UITableViewAutomaticDimension on the table view. I have tried removing the cell and the table doesn't jerk. It's defiantly the stack view causing issues.
I set my estimated row height to as close as possible to the calculated height tableView.estimatedRowHeight = 270. No affect. I have also tried implementing the delegate and it makes no difference. I have tried many combinations or sizes and the result is the same. Any idea on what I am doing wrong here? Do stack views in cells just suck?
I think you are on the right track about estimatedRowHeight causing trouble. I encounter this jerking problem and in pretty much every tableView with varying element size. What usually does the job is "caching" cell heights and returning them in delegate, something like:
class MyViewController: UIViewController {
fileprivate var cachedCellHeights = [IndexPath: CGFloat]()
//your code here
}
extension MyViewController: UITableViewDelegate {
public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cachedCellHeights[indexPath] = cell.frame.height
}
public func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = cachedCellHeights[indexPath] {
return height
}
return 270
}
}
It should work as long as you configure your cell (i.e. add new views to stack view) in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath).
The same applies to section headers.
I have a tableView, and within each UITableViewCell (call this parentCell), I have another tableView which has cells (call this childCell). I am using UITableViewAutomaticDimension to dynamically resize both of the cells height. I am successfully able to resize the height of the childCell this way, however, I am not able to apply UITableViewAutomaticDimension to the parentCell, since there when heightForRow is called, the childCell's height have yet to be estimated.
Is it possible to use UITableViewAutomaticDimension to estimate the parent cells height, which will be the height of all the childCell's height added together? Or am I going to have to do this manually?
//in ViewDidLoad
parentTableView.rowHeight = UITableViewAutomaticDimension
//in ParentCell's tableView's cell for row
cell.childTableView.rowHeight = UITableViewAutomaticDimension
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
The only way to do this was to use sections instead of placing a tableview within a cell.
I have a problem with my UITableView sections (and their height, I guess).
Within a section header, I have a view (named cornerRadiusView) within which there are few labels. These labels have dynamic content (fetched from a REST service). So whenever a UILabel height is increased, I am increasing the height of the cornerRadiusView to properly accommodate the content.
The problem is, all this works as expected only when I scroll my tableView. Till then, the heights are improper.
Here I am posting GIF to show what's going on.
I can give more details and code as needed. Could someone please look at where there is a problem?
You can use below functions
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
And reload table view in below method
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableview.reloadData()
}
And if you are maintaining dynamic height then manage those height in cell
override func layoutSubviews()
{
}
I have a UITableView(Table 1). Inside UITableView Cell I have an another UITableView(Table 2).
In Table 2 the rows's height is UITableViewAutomaticDimension.
My requirement is - I want that Table 2 should not be scroll and takes its full height as per number of rows inside it.So, As per this Table 2 's height I need to set Table 1's row height.
I am using Table 2 's contentSize.height, but its not working. I searched a lot but found nothing.
Code :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
let cell = tableView_First.dequeueReusableCell(withIdentifier: "SecondTableViewCell") as! SecondTableViewCell
return cell.second_TableView.contentSize.height
}
Update:
I have debugged the code and found Table 2's cell's estimated height effects the height of Table 1's cell.
i.e- If estimated height of Table 2's cell is 100 and these are 5 cells. Then this cell.second_TableView.contentSize.height gives me 500. Which is wrong.Because cell has different height 10, 20, 30, 40, 10.
Any suggestions will be appreciated.
Thanks!
May you are getting the wrong result because of below two reasons
When you are getting cell.second_TableView.contentSize.height that time your cell.second_TableView might not be loaded completely thus you are getting wrong height.
You are dequeuing new cell rather getting existing loaded cell.
Please try below code:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
//Get existing cell rather deque new one
let cell = tableView_First.cellForRowAtIndexPath(indexPath) as! SecondTableViewCell
//This will force table view to load completely
cell.second_TableView.layoutIfNeeded()
return cell.second_TableView.contentSize.height
}
Hope this will solve your problem.
write this two lines in viewDidLoad,
tableView.estimatedRowHeight = 241
tableView.rowHeight = UITableViewAutomaticDimension
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I have a table view controller with a navigation controller, and when there is no data for the table view, I want to display a single table cell with instructions on how to add new data. I can display the table cell, but I do not understand how I can get the height of the cell to span the visible height (table height - navigation item height). My goal is to have the label inside of my table cell be vertically centered in the device. I've tried using self.tableView.frame.height, but that gives me the scrollable height, which is larger than the visible area.
Edit: I failed to mention I'm doing this from tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat.
I have found a Good Enoughâ„¢ answer to my own question:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
tableView.isScrollEnabled = false
return tableView.frame.height - (self.navigationController?.navigationBar.frame.height)!
}