I've got a static UITableView in my storyboard that has a combination of system cells and custom cells. In order to make the custom cells look like the system cells, I've added a 15 point constraint from the front of the UILabel to the cell's contentView (to match the default separator inset of 15 points).
This strategy works well when the table view is portrait, but it looks like the constraints shrink when in landscape, as seen below:
Portrait:
Landscape:
You can see in the above image the "BUG REPORTING" section title, "Report a Bug" label (which is positioned by the system cell), and the line between the two cells are all 15 points away from the contentView's left side, but the "Logging" label is closer.
I've tried constraining the labels to the contentView with margins on and off, and the result is the same. The constraints for the custom labels even report different constant values when they're obviously the same shorter distance from the contentView's left side.
Does anyone know what's going on?
Try creating an IBOutlet for the label's leading constraint, and modifying it before the cell is displayed:
func tableView(_ tableView: UITableView, willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath) {
let leftInset = cell.separatorInset.left
cell.labelLeadingConstraint.constant = leftInset - 8
// - 8.0 accounts for constraint to margins in autolayout
}
Or, you could use size classes to set a different constraint for the Compact Height size class:
Then, simply set the constraints' constants to 12 instead of 7 (or 20 instead of 15, if margins are not used).
Related
How would I make it so that the table view cells have a certain aspect ratio.
How do I achieve this.
If possible, please given an example of w:h 16:4, and is it possible to set this aspect ratio in the interface builder on the storyboard.
Any help is much appreciated. Thanks in advance.
You can do this by giving the tableView a height proportional to screen and in heightForCellAtRow
return heightOFTable/numberOfCells
There should be a delegate function you can call to adjust the height of the cells based on the indexpath. something like:
func tableView(_ tableView: UITableView, heightForRowAt
indexPath: IndexPath) -> CGFloat {
return self.tableview.frame.width / 4
}
You can do it in Storyboard like this. Embed a UIView in your template cell, you can make it transparent and put it in the back. Stretch it to the edges and set constraints to all four edges. Now, make the a width constraint with same width as its superview. Then add an aspect constraint 16:4 with a priority of 999. The priority is needed to resolve a layout conflict you will otherwise get because of how sizing is working.
I'm having a problem with my table view cells as they do not adjust automatically with its content.
I have a label for a title and another label for a name. There is a text view below the two labels which is never displayed when the simulator runs.
This is
what the Table View Cell is supposed to look like, however, this is what the Table View Cell displays.
I have pinned all elements inside the table view cell to the content view using constraints. I read up that adjusting the table view cell height itself will not work, so, I have to adjust the height from the table view itself.
It is set to automatic but it is not adjusting as seen here. I have also tried to set the estimated height to automatic but to no avail. The only solution was to set a custom height but it would look extremely weird if the text view contains only a few text as there would be a large white space. I did not add any code at all to adjust the size.
These are the following constraints:
Table View
Name Label
Title Label
Text View
First You need to add height constraint for textview and add its IBOUTlet then you need to override the updateconstraint of cell and do following in update constraints method.
override func updateConstraints() {
super.updateConstraints()
self.textViewHeightConstraint.constant = self.textView.contentSize.height
}
and also for name label add bottom constraint.
By default the UITextView will not resize itself to fit its content. While you could use #Waqas Sultan approach, I would recommend to let the textView size itself. To achieve that, just use this:
textView.isScrollEnabled = false
Or, in storyboards, find the Scroll Enabled attributed and uncheck it.
This would make textView to size itself.
However, from the constraints you show it is hard to tell if there are really enough constraints to determine the proper frames for all the content - there are constraints related to Review label, but who knows how you constrained that label.
Not seeing all the relevant constraints in the tableView cell, I cannot guarantee that this will be enough to make it work as you expect (you might have forgotten about just a single one constraint, and it might be messing up your whole layout).
Hey buddy i would like you to try this way.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == desiredIndexPath { // the index where you want automatic dimension
return UITableViewAutomaticDimension
} else {
return 100 // the height of every other cell.
}
}
note: Make sure that you do not give height to the label. Otherwise the label wont expand according to content.
I have 4 components in my cell.
UIView
UITextView
UIImageView
Another UIView on top of the UIImageView
UIView
UIView
These content can be changed according the data that comes from the server(Sometimes it needs to hide the 3rd image view, sometimes 5th UIView). I'm using auto layout and with the auto layout what is the way to change height of the cell?
You can achieve this easily by using UIStackView. Stack views are a powerful tool for quickly and easily designing your user interfaces. Their attributes allow a high degree of control over how they lay out their arranged views.
Here is link for tutorial - Tutorial
If you hide a view from stackview it conveniently disappears from the layout, but it's still a subview of the stack view. So you don't have to do anything special if you want to bring it back later on. And by using self sizing cells, cells will automatically expand or collapse based on stack view height.
Do following steps:
When you hide any component give that component frame height as 0 and reload tableview. If you giving any component constant height then take outlet of height constraint and make it zero and specify its constant height again when you unhide.
When you unhide give him specific frame height and reload tableView.
heightForRow must returnUITableViewAutomaticDimension
As you already taken components from the storyboard so compiler understands the height of cell and work accordingly.
If you still facing issue you can ask.
this two methods are use for dynamic cell height
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
I post this for other man meet my issue.
Do not apply any change that will change the cell height in layoutSubviews, like hidden view or change any view's height.
A picture tells a thousand words, so here's the image of my UITableViewCell with my constraints.
I have a view pinned to all edges of the content view, and inside there's another view with a fixed width and height, pinned to the bottom and top of the superview. I am trying to center the x axis of this view to its superview. Running on a device everything looks okay, but interface builder is throwing an error on the outer view, saying it needs constraints for Y position or height. Can I somehow bypass that in interface builder? Or am I missing something fundamental about self-sizing table cells?
I am sizing my table cells with:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Don't worry. You have done everything right.
The warning is about the ambiguity raised due to two different heights of the tableViewCell.
Height 20 arising due to your constraints.
Height provided (or default height i.e. 44) in the size inspector.
Just change the cell height to 21( or 20 if your table view has no separators). The ambiguity would be resolved.
Note : Its 21, because the cell height is 1 + the height of the cell content view. This 1 point is for the separator line.
Also even if you don't do any changes the UI will be fine as this ambiguity would be solved at run time where height is calculated fro the content. Hence height fed in the IB is overridden by the calculated height, hence no issues.
I'm having three labels in my static table view cell and the middle label should be a multiline one.
I'm setting these two lines in viewDidLoad()
self.tableView.estimatedRowHeight = 130.0
self.tableView.rowHeight = UITableViewAutomaticDimension
The storyboard looks like this
Here are the constraints for each subview
Top label, middle label, bottom label, button
I've also set the number of lines for the middle label to 0. However it only shows one single line, instead of multiple lines. I guess it must have something to do with content hugging or content compression priorities or it's because my I'm using a UITableViewController with static cells.
UPDATE
If I change Vertical Compression Resistance Priority of the middle label to 751 and Vertical Content Hugging Priority to 250, the label shows multilines, but the cell does not get resized, so the top and the bottom label are outside the cell now.
UPDATE 2
I've just created a sample project and it turned out that it works with dynamic cells as expected but not with static cells. You can download the sample project here: https://dl.dropboxusercontent.com/u/67692950/ResizingCell.zip
I cloned your sample project. I think the problem is that you don't need to set UITableViewCell's height.
This is the one simple solution.
・To set Row Height "Default" in Table View Cell.(Unchecked Custom)
In this case, it works.
Download the sample project that I implemented here:
https://www.dropbox.com/s/w8q6ov9qjfxu1l3/ResizingCell.zip?dl=0
But the other way is that you calculate UITableViewCell's height from UILabel's height.
If you customize cell more complicatedly, it is better to isolate cell as a Custom cell.
Firstly, open storyboard, set your tableview row height to be 100, uncheck custom row height for the tableview cell, which value is currently 100.
Secondly, like #DBoyer said, call layoutIfNeeded. If you see "Unable to simultaneously satisfy constraints, Will attempt to recover by breaking constraint X", lower X's priority to 999. I think the warnings may have something to do with that when you get the cell, cell frame is CGRectZero.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
cell.layoutIfNeeded()
return cell
}
You need to either call layoutIfNeeded on the cell after setting the text of the multiline label or set the labels preferredMaxLayoutWidth
Use aspectRatio constraint for labels. Its puspose is to change width aswell as height according to need.This will help