The layers: UITableViewCell -> UIStackView -> UILabel, table height is set to automatic dimension.
Run it, everything is fine
After some scrolling, the bottom of the multiline label gets cut off
UILabel and stack view settings:
lay out constraints for the stack view:
I've tried to set the line break to word wrap, call sizeToFit on the label, neither of them works for me. Any clues?
Since the problem occurs because of scrolling, this seems to be the problem related to TableView reusing the cells on scrolling. Hence reset all the values of cell that you are using (which includes dimensions as well if any). On scrolling, the current cell content gets displayed in some other cell which is being reused.
One way I have solve that kind of problems in the past is to put the UILabel inside a UIView as a container view. Then put this container inside the UIStackView instead of putting the label directly in the stack view.
You can also try to play around with compression resistance priority because the label seems to be shrinking because its compression resistance is not high enough.
Related
I have a TableViewController with a custom UITableViewCell containing a single UILabel. The label will receive variable lengths of text, and should resize in height accordingly. I want to use auto layout, iOS10++.
However, it seems that the cell is preventing the label from expanding its height.
I have constraints on the label to pin top, bottom, left and right to the cell's contentView.
The label number of lines = 0, and is set to line break mode = WordWrap.
I have set the self.tableview.rowHeight to UITableViewAutomaticDimension, and have set the estimated row height to various sizes with no success.
I have increased (and decreased) the label's content hugging priority and and the vertical compression resistance, but this has no effect.
This sounds like a duplicate of so many other questions, but none I have read has solved my problem.
Some clues I have noticed:
1) If I remove the label's bottom constraint, the label expands correctly, but (of course) the cell doesn't expand, so the label cannot be fully seen after it expands below the bottom of the cell. So I conclude that the cell is preventing the label from expanding.
2) if I rotate the tableview to landscape and back to portrait, the first cell expands correctly. So something that occurs during the rotation solves the problem at least for the first cell, and also proves that the cell and label can expand as required.
I feel something is not right, but cannot figure it out. I am very close to going back to the old version of calculating the height manually and returning it in heightForRowAtIndexPath delegate method.
I would appreciate any suggestions. Thanks in advance.
I finally figured it all out.
In summary, I was configuring the cell (including setting the label's text) in tableView willDisplayCellAtIndexPath...
But it seems (obvious really) that for the autoresizing to work, the cell must be configured in tableView cellForRowAtIndexPath.
Moving the configuration into cellForRowAtIndexPath and suddenly everything started working perfectly.
Hope this helps anybody who has the same problem. I struggled with it for days.
I am having a doozy of a time trying to figure this one out:
I have a UITableViewCell with a fixed sized UIImage (250 x 250) pinned to the top of the cell's View and a UILabel of variable text size underneath with its top pinned to the bottom of the UIImage and its bottom to the bottom of the cell's View.
I have a use case where an image is not always guaranteed and so the image view purposely collapses to 0 height so it does not break autolayout on the UILabel's top pinning.
I assumed that this would allow the UITableViewCell to shrink down to the size of the label but instead, it stays the default height and autolayout stretches the label's height (to maintain the pinning to the top and the bottom) with the text centered in the middle.
I used all the usual suspects, UITAbleViewAutomaticDimension and estimatedRowHeight blah blah (what you would probably suggest first!) and it was to no avail.
What am I doing wrong?
I did see something about changing the Priority for the constraints in IB to 250 instead of 1000 so they could break. And also some references to resizing the UITableViewCell manually (lame and nasty) by calling requiredHeight() on the UILabel which broke the layout, so what am I doing wrong here? Thanks!
I have a use case where an image is not always guaranteed
For this situation you can create 2 type of UITableViewCell: the first one with UIImageView and the second without it. Then, in cellForRowAtIndexPath init the cell you want.
After an extended amount of time searching for an answer and fidgeting within my project, I have decided to come here.
The issue: I have created a UITableView in which the cells expand when a user taps on them. This part is perfect, however, I can not seem to get either the constraints or heights correct. The cells are each 1/3 of the TOTAL screen (including status & navigation bar) before they are tapped, and then they expand to be 1.75 times that size. Originally there is just a UIImageView that takes up the unrevealed cell and once it is taped it is supposed to reveal a UIScrollView (of which contains static data.) However, I can not seem to get this to happen, when I add constrains I either get overlapping ImageViews that opens to a part of the ScrollView, squished images, or a properly working expanding cell but once the cell opens the image expands with it (which I do not mind) but the ScrollView is not there.
I have attached a screenshot of a reconstruction of the interface builder. The UIImageView is set to 300, the ScrollView to 215. Screenshot of Interface
Try to check content hugging priority and content compression resistance priority of your image view and scrollView.
func checkHeight() {
levelsView.hidden = (frame.size.height < P1Cell.expandedHeight)}
you should check this return no or yes,
and how about change frame to bounds.
Hi I need help with understanding how to resize cell based on its content.
So first of all of course I found many links:
iOS: Multi-line UILabel in Auto Layout
https://www.youtube.com/watch?v=CkvZEJ7dIfw
https://github.com/williamhqs/GSTableViewDynamicHeight
As we said about git example (last link) I can't understand how to change some label and make it works. For example if I delete UILabel and create new one and bind it with content property (content - it is IBOutlet property of bottom label). I seems lost some setting and cell won't stretch.
So I think I don't know to much understanding how to do it.
What I want to understand:
How to setup auto layouts in the storyboard or programmatically.
Which thing I should handle programmatically to make it done.
How the preferred size affects on label. Do we need every time use bonds of superview as a preferred size?
Also in the git example we have one label that changes itself size. What if we have 2 UILabels with dynamic content how to setup it?
If you have some links or videos please drop them here, because I really stuck. Thank you!
I know it's duplicated question but I can't understand how to setup it.
To make Self Sizing Cells works there is three steps:
Setup correctly the constraints of the cell (most important the top and bottom constraints)
Specify the estimatedRowHeight of your table view
Set the rowHeight of your table view to UITableViewAutomaticDimension
for step 2 and 3 it's so easy just add these two lines in you viewDidLoad method
tableView.estimatedRowHeight = 44.0 // or whatever you want
tableView.rowHeight = UITableViewAutomaticDimension
for step 1 which is the most important part of self sizing process
what you need to keep in mind is that "self-sizing needs to get its size from your constraints."
Basically we need to make sure that top space and bottom space constraints of our cell is correctly set up here is an example :
just two labels with the constraints top,bottom,right and left space to each other and to container (see image) the UILabels Lines property is 0 so that you allow have multiple lines
Another example from a project that I am working on:
bottom line:
The label constraints should push against the size of the table view cell and make it taller. So always check the top and bottom constraints.
Also you may run intro trouble working with UILabel with multi-lines because
The intrinsic content size of UILabel and NSTextField is ambiguous for
multi-line text.
so make sure always to setup the preferredMaxLayoutWidth property of yout label:
- (void)layoutSubviews
{
[super layoutSubviews];
self.contentLabel.preferredMaxLayoutWidth = self.contentLabel.frame.size.width;
}
for more infrmation about this issue here read :
iOS Autolayout multi line UILabel
iOS multi-line UILabel in Auto-layout
preferredMaxLayoutWidth
And for more information about Dynamic Table View Cell Height in general here is some useful resources:
UITableView Tutorial: Dynamic Table View Cell Height
Understanding Self Sizing Cells and Dynamic Type in iOS 8
Self Sizing Table View Cells
Mysteries of Auto Layout, Part 1 (wwdc 2015)
Not sure if it will apply to AutoLayout, although when laying out a cell programmatically, running "layoutIfNeeded()" fixed my cell content stretch issue.
layoutIfNeeded was ran at the end of a configure method, used to map values (view model) to UI objects (views)
I have been struggling with this for a few days now, and I am looking to see if someone can help me with this AutoLayout problem.
In my iOS7 application, I have a UIView that has a UIScrollView and inside it a UIView(container) with some elements positioned. I have in there, a UIImageView, UITableView, UICollectionView, UITextView and a MapView. There is no height constraint on the UIScrollView and the container UIView. There are no height constraints on the UICollectionView and the UITextView.
What I want to accomplish is
The UITextview should expand to the content size as in all the text should appear without any vertical scrolling enabled for the UITextView.
The UICollectionView should always show all items and there should not be any scrolling enabled there as well.
Overall, I want a UIScrollView with items in it, that scale based on content. I have tried numerous things, but failed.
If anyone has pointers or suggestions on how to go about doing this, it would be very helpful.
OK, I would go about this in a completely different way.
First, get rid of the scrollView completely.
Just use a UICollectionView for this entire interface.
The UICollectionView can take a UIView for a section header. Make this UIView with your UITextView inside. You will need to manually calculate the correct height for your UITextView (and UIView).
Something like...
CGSize size = [theText sizeWithFont:<the font used> constrainedToSize:CGSizeMake(desiredWidth, CGFLOAT_MAX)];
Then just populate your collection view.
By doing this your collection view will control all the scrolling. Because you have set the textview to the correct size in the header you will have all the text there.
This is how I would go about it:
I assume your issue is with the height of the views, that affect the scrolling.
In the textViewDidChange: I would set the frame of the UITextView same as it's contentSize. When they are both the same, scrolling gets disabled.
After populating your UITableView and calling reloadData, I would set it's frame same as it's contentSize.
The mapView (MKMapView, I suppose) has the same frame throughout, I suppose. So you just use it's fixed height. If it changes height, you must store it's changing height each time it changes.
Once you have all the heights, add them up, and set the frame of the outer view same as then combined height of the inner view. Iterate this to all nested views, beginning from innermost views, and moving to outer views.
The catch here is, every time your content changes, the frames have to be resized. Hence changing the frames in textViewDidChange:, after reloadData, etc makes sense.
EDIT : One thing you might want to do first is, getting rid of redundant views. Your view hierarchy seems Rube Goldberg to me. The lesser views you have, the lesser work you will have to do.
Ok.. so I solved this problem by creating a IBOutlet for my NSLayoutConstraint on the UITextView in question.
I simply computed the height and then applied it on the constraint and it worked..
#Fogmeister - Your solution will also work, but it would require me to rewire a whole UI page.. Your approach is definitely a feasible one and shall keep in mind for future iOS apps..