I am creating a tableView with custom cells in which each cell can have different types of views ranging from key-value pair labels, map, buttons , list and more depending upon the data coming from the server and those views will be populated accordingly. I have created custom XIB for each view type which i will be using
So for this I took a parentTableView whose cell will have a childTableView whose each cell will be the different type of view depending on the data from the server
NOTE - Call and Navigation button and Assigned label are not cells but are added on top of the cell
Now I have two questions :
How can i make the childTableView to disable scrolling feature and take the full height of its content (In the image after last assignedTo, there is a priority field which is currently clipped as i have defined the height of the tableView cell to be 200 )
Dynamic height for parentTableView's cell (which is almost similar to first question)
I tried setting rowHeight and estimatedRowHeight for parentTableView but it is collapsing the cells
parentTableView.rowHeight = UITableViewAutomaticDimension
parentTableView.estimatedRowHeight = 300.0
remove parentTableView.rowHeight = UITableViewAutomaticDimension
and update your cell height to calculated cell.tableView.contentSize.height
ref:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = tableView.dequeueReusableCellWithIdentifier("identifier", forIndexPath: indexPath) as! CustomCell
return cell.tableView.contentSize.height
}
Related
I'm using the typical method of dynamically sizing table view cells that contain text views in them:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
This works just fine for the cells I actually instantiate and use, but it has a strange side effect: the empty cells that the table view shows below instantiated cells end up resizing their height alongside whichever custom cell I'm currently editing.
So when I input three, four, or more lines of text into a newly added custom cell...
...all the other prototype-based custom cells already filled in the
table remain unchanged
...the custom cell being edited resizes dynamically as intended
...but all the "ghost" cells below the last custom cell in the table
view end up dynamically expanding alongside the custom cell that's
being edited
My first thought was that it must have something to do with how I dequeue cells, and specifically what I return when dequeueing doesn't happen:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let myCell = tableView.dequeueReusableCell(withIdentifier: "myCustomCell", for: indexPath) as? CustomCell {
return myCell
} else {
return CustomCell()
}
}
But I tried returning both my custom cell and just UITableViewCell() in the else block and the result is the same.
Does anyone know why this could possibly be happening and/or how to get around it?
In my tableview, every cell will be different and determined by a JSON response from server. And there will be infinite possibilities. So defining a prototype for each type of cell is not possible.
For example, one cell will have labels and buttons, another cell have images and buttons in different orders.
How to achieve this dynamic structure in tableview cells?
Currently what I am doing is: adding views as subview in cellForRowAtIndexPath but scrolling is very laggy this way.
How to achieve this without affecting performance this much
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! MyCell
for myview in data[indexPath.row].myviews{
cell.addSubview(myview)
}
return cell
}
If you're using a table view then your content is going to scroll vertically, right?
There is a physical limit to the amount of UI that you can put horizontally. Limited by the screen size.
So I'm guessing your UI parts are being laid out vertically in the cell?
So instead of laying out a button, label, image, another button, and a text field vertically in a cell...
Create a cell type called ButtonCell, LabelCell, ImageCell, MultiLineLabelCell, TextFieldCell, etc...
So now, instead of creating one cell with all these elements added. You instead create multiple cells each containing one type of UI. Now you can dequeue your cells in any particular order (driven by your JSON) and won't lose the performance.
The only solution I see is to have empty cell and add/remove subviews as needed. But you should add new subviews to a cell only if you did not add them before.
For example:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! MyCell
if cell.contentView.viewWithTag(1) == nil {
let label = UILabel()
label.tag = 1
cell.contentView.addSubview(label)
}
let label = cell.contentView.viewWithTag(1)
// label config there
return cell
}
Also don't forget to add subviews to cell's contentView not to cell itself.
I have UITableView in UIViewController in this view controller total 3 tableview or 2 UICollectionView. so in this one tableview contain many cells or cells data are not static its dynamic according to server. So, I create the table view height outlet & its set on cellforrowatindex function of tableview.
So, we use to set height tableview_height.constant=tableview_height.constant+cell.frame.size.height using this code my problem showing whitespace on the end of UITableViewCell. If I increase the cell then cell are cut from the bottom. I am giving below constraint show in the pic.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.row == 0
{
tableview_height.constant = 0
tableview_height.constant=tableview_height.constant+cell.frame.size.height
}
else
{
tableview_height.constant=tableview_height.constant+cell.frame.size.height
}
return cell
}
Check my answer on the almost same question.
How to increase the height of parent view according to height of UITableView in swift?
It is the best way to achieve what you want, because it does not depend on your table settings or if you have header/footer/custom insets/whatever.
Hope it will help.
I am trying to insert a lot of views into UITableViewCell.
I add view and calculate required constants. And I can't resolve one problem. Inner labels can be bigger than one line and when UITableView only initialized it didn't displays correctly: some cropped labels, wrong height and etc.
But when I reload tableview or scroll to bottom elements and scroll back to incorrect one cell all views displays correctly.
EDITED
Example: I have UITableViewCell. Every cell contains number of attributes(separate views). Each attribute view has title(gray text) and attribute value(single view again). Each attribute value view may have different height. And I assume height doesn't calculates right at the first time.
When I build UITableViewCell firstly I build all of attribute views and after that I add each view to Cell and calculate constants.
I have solve problem.
When I got UITableViewCell it frame has width 325 but tableView frame width is 375. Because of this inner views were build incorrect way. Now I just set contentView of Cell to tableView frame.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "ListCell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? ListViewCell
cell!.contentView.frame = tableView.frame
// additional setup
return cell!
}
I have two prototype cells. Most of the UI are the same except one has a image view and the other one don't. The situation is that in cellForRowAtIndexPath, when I set the value for these cell's labels. I have to set them each time in two cells. Can I just set them once and only set the image for the cell only has a image view?
For example:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let place = places[indexPath.row] as Place
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("ImageCell", forIndexPath: indexPath) as ImageCell
cell.nameLabel = names[indexPath.row]
cell.screeNameLabel = screenNames[indexPath.row]
cell.createAtLable = place.createdAt.shortTimeAgoSinceNow()
cell.profileImageView.hnk_setImageFromURL(imageURL)
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("BaseCell", forIndexPath: indexPath) as BaseCell
cell.nameLabel = names[indexPath.row]
cell.screeNameLabel = screenNames[indexPath.row]
cell.createAtLable = place.createdAt.shortTimeAgoSinceNow()
return cell
}
}
As you can see, both cells have the same nameLabel, screeNameLabel, createAtLable. How do I only have to set them once? The above code is only a example. My current project, I have a lot of ui in the cells and they are basically the same except one has a image and one don't.
And by the way, what's the best way for this situation. When a cell contains most the same components, only a few components are different. Are using multiple prototype cells the best way?
You can solve it by auto layout. You can use the same cell prototype. What you need to do is set the height of image view to "greater than or equal to 0" if you want to let it expand according to different image height or "less than or equal to some constant if you want the image view height to be fixed. Since imageView has intrinsic content height and width it will expand or shrink according to what you load. The key is to make image view height 0 when there is no content.