AutoLayout Constraints For Dynamic Cell Height - ios

I have been searching in stack overflow from long time,i found some questions related but not perfect.
Can someone explain In detail what are the steps to make label grow its height based on text that is in tableview cell.I want to increase the labels height and then the cells height.
Thank You.

For iOS 8+ you can find explanation and example here
For iOS prior 8 version it's more complicated to do this. You should manually calculate the height of the cell and then provide this heigh in delegate methods of a table view (heighForRow at index path). Hope this will help you.

it boils down to this
var myRowHeight: CGFloat = 100 //initialize this to some value close to what it will probably be
override func viewDidLoad() {
//control row height for variable text size
tableView.estimatedRowHeight = tableView.rowHeight
tableView.rowHeight = myRowHeight
}
override func viewWillAppear(animated: Bool) {
//set row height right before view appears so autolayout has time to estimate it
tableView.estimatedRowHeight = tableView.rowHeight
tableView.rowHeight = UITableViewAutomaticDimension
}
This is the solution that works for me.

Related

how to make scrollview grow based on collection view number of rows in ios?

i have a scrollview which has a picture, text, button, label and then a collectionView whose number of rows is dynamic in nature. Its like collectionview will grow in height and hence the scrollview should assume collectionView height as well as other elements height to get a smooth scroll. How to achieve this using auto Layout in ios?
So my doubt is how to make a dynamic scrollview height based on a growing colelctionview or tableview height.
You can increase the height of CollectionView Height Constraint , connect Height contains to your ViewController and than .
how to connect constraint to outlet ?
let height = self.collectionView.contentSize.height;
self.heightConstraints = height;
self.scrollView.contentSize = CGSize.init(widht:self.scrollView.frame.size.width,height:height)
FOr Swift 4.2
override func viewDidLayoutSubviews() {
let heightFilterCOll = self.filterCollectionView.contentSize.height
self.filterCOllectionViewCOnstraintHeight.constant = heightFilterCOll
self.ScrollView.contentSize = CGSize(width:self.ScrollView.frame.size.width,height:heightFilterCOll + 77)
}
These methods didn't work for me. Try,
self.collectionView.reloadData()
DispatchQueue.main.async {
self.heightCollectionViewConstraint.constant = self.collectionViews.collectionViewLayout.collectionViewContentSize.height
}

Auto size view on tableViewController

I am having a view at the top of my tableViewController. The view is called viewBackground. It is there to show the post the user clicked on and the table cells will show the comments.
What I want to do is to resize the viewBackground depending on the size of the label theLabel. I have done this in the cells by setting the label in the cells to 0 lines and by implementing this little code :
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 205
How do I do the same with my viewBackground?
This is a picture of the tableView:
You can create table view with two sections. First section will contain selected post; second section - comments. If you need, i can provide some code.
Added this code and it helped!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
var headerFrame = headerView.frame
//Comparison necessary to avoid infinite loop
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
tableView.tableHeaderView = headerView
}
}
}
I suggest to make a header for your current tableView -instead of adding an external view above it-, and then you can follow this answer, it should helps you of how you can calculate the label's string height and returning it in the tableView(_:heightForRowAt:) method.
Hope this helped.

How to make a self sizing basic UITableViewCell?

I know how to make a custom self sizing cell. But for some reason I'm facing challenges when trying to make a default one multi-line.
What I currently want is a cell which only has one label. So the default one with a built-in style "Basic" seems to be the best solution for something as simple as that. However it only shows 2 lines of text.
My current set-up: a static UITableView and a UITableViewController containing outlets to some of the cells that need to be configured.
Things I tried:
set number of lines to 0
set table view's row height to UITableViewAutomaticDimension
override heightForRowAtIndexPath so that it always returns UITableViewAutomaticDimension
call sizeToFit, setNeedsLayout, layoutIfNeeded on the cell and/or content view and/or text label
set custom cell height to 0 in storyboard
increase vertical and horizontal content hugging priorities for the label
EDIT:
I guess I wasn't really clear about what exactly is the problem. I'm not using a custom cell. I'm trying to get away with the basic one.
This means you can't add any constraints to its label. Sure, you can programmatically but since everything is managed internally for Apple's built-in styles it may result in a conflict.
Additional details:
At this point (as I mentioned above) I have a UITableViewController with outlets to specific cells: #IBOutlet weak var descriptionCell: UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Is it really possible? Since I already spent too much time trying to avoid making a custom cell I'll finally go make it. Anyway any solution is welcome.
It's no need to do following two.
call sizeToFit, setNeedsLayout, layoutIfNeeded on the cell and/or content view and/or text label
set custom cell height to 0 in storyboard
And you should check you label's constraints. For example, it should has fixed width at run time and has constraints with cell's top and bottom. So the cell will grow itself.
Try this approach:
Set number of lines to 0
Set table view's row height to UITableViewAutomaticDimension
Override heightForRowAtIndexPath so that it always returns UITableViewAutomaticDimension
NsLayConstraints for label:
top = cell.top
bottom = cell.bottom
leading = cell.leading.padding
trailing = cell.leading.padding (Padding is optional)
It works for me. All you need to do in your code is
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 44.0 // or whatever height is closest to what your cells will be
tableView.rowHeight = UITableViewAutomaticDimension
}
Everything you listed after "set table view's row height to UITableViewAutomaticDimension" is not necessary. Just set number of lines in your cell's label to 0 like you did and include the code above.

How to stop uitableview after all the rows are done

The title might not be so clear but it was really hard to express it so I will do my best to explain here.
Look at this image:
I want the UITableView to stop entirely after all the rows are done. Meaning after the footer there should be no more white view.
I think what is causing this is the constraints that i have put. But I need my constraints to make it look good in all possible sizes etc. So my question is how can something like this be solved? I am using SWIFT.
This worked like a charm. Thank you #tahavath for pointing me to this direcation
override func viewWillLayoutSubviews() {
dispatch_async(dispatch_get_main_queue(),{
//This code will run in the main thread:
var frame = self.tableView.frame;
frame.size.height = self.tableView.contentSize.height;
self.tableView.frame = frame;
});
}
EDIT
It does work however this will be a problem if the table is bigger than the screen. When trying to run this on iphone 4s it looked terrible.
Try the following code...
Just include the following code... give your table view an automatic dimension.
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
return UITableViewAutomaticDimension;
}
Also add the following code where the view loads
tableView.estimatedRowHeight = 89
tableView.rowHeight = UITableViewAutomaticDimension
Why don't you set
tableView.backgroundColor = UIColor.clearColor()
and then you set
cell.backgroundColor = UIColor.whiteColor()
Edit (not sneaky approach)
tableView.frame.size.height = tableView.contentSize.height
But there is a problem, if the screen height is not enough to contain tableView content, it will be bad.
Here's the right way
tableView.frame.size.height =
tableView.contentSize.height > UIScreen.mainScreen().bounds.height ? UIScreen.mainScreen().bounds.height : tableView.contentSize.height
Because the table thinks there is a footer to show, it doesn't display any cells beyond those you explicitly asked for.
Set a zero height table footer view in your viewDidLoad method
self.tableView.tableFooterView = UIView(frame: CGRectZero)
Or
tableView.tableFooterView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.tableFooterView = UIView()
}

iOS Auto-Layout: Dynamic height for table view cell

I have a table view with a bunch of cells (custom cell, which only has its content view).
In tableView:cellForRowAtIndexPath: I'm adding a predefined UIView (which has several subviews) to the content view of the custom cell. I set up all constraints for the UIView and its subviews before.
Last but not least, I set the vertical and horizontal constraints for the content view of my custom cell (superview) and the UIView, which was added before (subview).
The constraint strings look like this:
H:|[view]|
V:|[view]|
Unfortunately, I still get the default height for all table view cells. I'm wondering If there's a way to let auto layout do the calculation of the height automatically according to content size.
Check out my detailed answer to this question here: https://stackoverflow.com/a/18746930/796419
It takes a bit of work to set up, but you can absolutely have Auto Layout constraints driving a completely dynamic table view without a single hardcoded height (and let the constraint solver do the heavy lifting and provide you with the row height).
Auto Layout won't help with the cell height. You'll need to set that in tableView:heightForRowAtIndexPath. I guess you're probably asking this because your cell heights are variable, not fixed. i.e., they depend on the content.
To resolve that, pre-calculate the cell heights and store them in an array. Return the value for the appropriate indexPath in the tableView:heightForRowAtIndexPath method.
Be sure to calculate content sizes on the main thread, using sizeThatFits of UILabel classes and such like.
If your calculation is intensive, do the majority of it off main apart from the view related methods such as sizeThatFits.
I solved the problem by using CGSize size = [view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; in tableView:heightForRowAtIndexPath:.
To set automatic dimensions for row height, ensure following steps to make, auto dimension effective for cell/row height layout.
Assign and implement dataSource and delegate
Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight
Implement delegate/dataSource methods (i.e. heightForRowAt and return a value UITableViewAutomaticDimension to it)
Swift:
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Don't forget to set dataSource and delegate for table
table.dataSource = self
table.delegate = self
// Set automatic dimensions for row height
// Swift 4.2 onwards
table.rowHeight = UITableView.automaticDimension
table.estimatedRowHeight = UITableView.automaticDimension
// Swift 4.1 and below
table.rowHeight = UITableViewAutomaticDimension
table.estimatedRowHeight = UITableViewAutomaticDimension
}
// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Swift 4.2 onwards
return UITableView.automaticDimension
// Swift 4.1 and below
return UITableViewAutomaticDimension
}
For label instance in UITableviewCell
Set number of lines = 0 (& line break mode = truncate tail)
Set all constraints (top, bottom, right left) with respect to its superview/ cell container.
Optional: Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data.

Resources