I have a main vertical stack view (Frame 1), that has a horizontal paging collection view with flow layout (CollectionView), which has a couple of cells (Cell). Each cell comes with a vertical stack view of a couple of labels (Title, Description).
Is there a way to let the tallest cell determine the collection view's height, while the main stack view width determines the width of the cells?
By default, the collection view is not visible when I use layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize (seemingly it does not "inherit" the cells' height).
For now, I worked around the issue by setting a fixed height for the collection view, and defined the item size manually in the collectionView(_:layout:sizeForItemAt:) (and the cells are flexible).
Since CollectionViews (and TableViews) don't have an intrinsicContentSize, there is no way for the layout engine to know the correct size of your collection without the appropriate constraints. A subclass is needed to provide this property.
In your subclass:
override var intrinsicContentSize: CGSize {
return CGSize(self.contentSize.height, self.superview!.bounds.width)
}
Also, don't forget to invalidate your content size when reloading data:
override func reloadData() {
super.reloadData()
self.invalidateIntrinsicContentSize()
}
For a more detailed explanation on intrinsicContentSize check Apple's Documentation
As the content is static, I think simply using UIScrollView is a pretty viable alternative here (as the dynamic nature of the collection view is not a requirement). The collection view could be a stack embedded into a scroll view, then the contains between the dimensions can be simply set upon initialization.
Related
I have a main vertical stack view (Frame 1), that has a horizontal paging collection view with flow layout (CollectionView), which has a couple of cells (Cell). Each cell comes with a vertical stack view of a couple of labels (Title, Description).
Is there a way to let the tallest cell determine the collection view's height, while the main stack view width determines the width of the cells?
By default, the collection view is not visible when I use layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize (seemingly it does not "inherit" the cells' height).
For now, I worked around the issue by setting a fixed height for the collection view, and defined the item size manually in the collectionView(_:layout:sizeForItemAt:) (and the cells are flexible).
Since CollectionViews (and TableViews) don't have an intrinsicContentSize, there is no way for the layout engine to know the correct size of your collection without the appropriate constraints. A subclass is needed to provide this property.
In your subclass:
override var intrinsicContentSize: CGSize {
return CGSize(self.contentSize.height, self.superview!.bounds.width)
}
Also, don't forget to invalidate your content size when reloading data:
override func reloadData() {
super.reloadData()
self.invalidateIntrinsicContentSize()
}
For a more detailed explanation on intrinsicContentSize check Apple's Documentation
As the content is static, I think simply using UIScrollView is a pretty viable alternative here (as the dynamic nature of the collection view is not a requirement). The collection view could be a stack embedded into a scroll view, then the contains between the dimensions can be simply set upon initialization.
I have a UITableView with different cells, within one of these cells is a UIStackView which contains multiple UIView's, the last one being a custom class that subclasses UICollectionView.
So the issue I'm having is that the collectionview within the stackview doesn't appear because the height is zero. To try and get around this issue, within the custom UICollectionView I've tried to apply a height within using the following piece of code.
override func layoutSubviews() {
super.layoutSubviews()
if !hasBeenLayedOut {
hasBeenLayedOut = true
self.apply(height: self.collectionViewLayout.collectionViewContentSize.height, width: nil)
self.layoutIfNeeded()
}
}
The only problem is because after the views in the stack views have constraints applied once I apply a height constraint, the stack view items shrink to adjust their content to the collection view.
My questions is it possible to figure out the height of the collectionview before layoutSubviews()? I've tried to use the collectionviewContentSize but it's always 0 which is why my collectionview doesn't have a height.
I am creating a collection view full of menu items. The collection view is supposed to be tall enough so that it fits perfectly in the size of view.
I can set the UICollectionView with a fixed height constraint, but if there are 20 items then that height might be too small or if there are 5 cells the height would be too big.
Is there a way to change the frames of the main view and the Collection view based off how many cells the view will have? Possibly in the viewDidLoad() function?
set the height constraint of the collection view in storyboard with any value , and hook it as IBOutlet say collectionHCon
override func viewDidLayoutSubviews() {
self.collectionHCon.constant = numberOfItems * itemHeight
super.viewDidLayoutSubviews()
}
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.
First of all this is not a question about how to automatically size the cells inside the tableview, moreover how to automatically resize the entire tableview.
So I have a scrollview which has a tableview and 2 other views as its subviews. The tableview's cells already automatically resize itself, again this question is not about the individual cells. However, the tableview does not resize at all.
What I have done:
1) Set up the tableview to have a top, bottom, leading and trailing constraint
2) Set the cells up to have auto layout enabled
3) * I do not know the cell size at build time
4) I have disabled scrolling mode on tableview
So long story short, how can I go along to get the tableview to resize itself?
Edit
The cells contain a label which can have various lines of text, so therefore the cells, which use auto layout, should then determine the height of the table view.
The following images show how the view is set up:
As you can see the tableview is only a small part of the view and since the scrollview from the tableview is deactivated there should, and aren't, any scrolling problems.
EDIT 2
This is actually how it should end however, i am calculating this on my own and everytime I want to make a small change to the cells the whole code, which calculates the height of the cell, needs to be rewritten and it is quite difficult for me to get the height just right.
Edit 3
Until now I had a height constraint on the tableview which I calculated manually, however removing this constraint and trying to let auto layout handle the tableview height size creates the following error:
Scroll View
Need constraint for: Y position or height
I can conclude therefore that the tableview does not know how to automatically calculate the height based on its cells with autolayout.
You don't need to create a height constraint or set frame whatsoever. Create a subclass of UITableView and recalculate its intrinsicContentSize every time its contentSize changes aka new data added or removed. Here is all you needed:
class SelfSizingTableView: UITableView {
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
setNeedsLayout()
}
}
override var intrinsicContentSize: CGSize {
let height = min(.infinity, contentSize.height)
return CGSize(width: contentSize.width, height: height)
}
}
You can change your UITableView's frame by using tableview.frame = CGRect(x: <some_x>, y: <some_y>, width: <some_width>, height: <some_height>)
If your UITableViewCells use auto layout then they should resize when the UITableView's frame changes.