I'm using sizeForItemAt to set the cell size for ONE view controller, but it seems that I have to return a result also for the other CollectionViews, the problem is that I don't have the size value for the others since it is defined in the storyboard. I'm trying this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if categorie_cv == collectionView {
let size: CGSize = categorie[indexPath.row].size(withAttributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 17.0)])
return CGSize(width: size.width + 40.0, height: categorie_cv.bounds.size.height)
} else if collectionView == risultati {
return THIS VALUE IS SET IN THE STORYBOARD
} else {
return THIS VALUE IS SET IN THE STORYBOARD
}
}
No, unfortunately you can not tell it to automatically use the intrinsic size of the element derived from its layout.
However if your layout would really allow for the intrinsic size to be configured non-ambiguously through AutoLayout/it's content, you can call UIView.intrinsicContentSize, possibly mixing with layoutIfNeeded call. I am not positive that this solution is 100% working though.
If I were you I would seek not the way to assign a delegate and implement sizeForItemAt but rather do define this size ALSO in the matters of the cell itself.
And by the way, actually, it's a bit of "will turn out NOT as you expected it to" to let the cells to determine their their content size. This can be very helpful and logical with UITableView, but layout calculation in case of UICollectionView is better to be determined by simpler, calculative approach.
That is, it's cheap to compute the width to be half of bounds width of collectionView and equal to height - rather then let the content freely layout itself using very dynamic content-compression rules and constraint priority evaluation. Typically, having all cells have absolutely nothing in common in terms of their aspect ratios, widths OR heights will really tend to output the undesirable results.
Related
I just can´t get familar with auto layout in Xcode. When I set trailing and leading constrains for Header Stack View, Bottom Stack View or the image between them, then the size (height/width) of my cell changes. Why does it happen and how can I avoid it? I think something isn´t right with the kind I build layouts. I am very grateful for any help.
I set the cell size with this code:
extension MainVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = view.frame.size.height
let width = view.frame.size.width
return CGSize(width: width * 0.42, height: height * 0.3)
}
}
My cell layout:
This is how the app looks when I use constrains for the Bottom Stack View.
This is without constrains for the Bottom Stack View (correct cell size).
Cells can now self-size with auto layout and ignore what you return in collectionView(_:layout:sizeForItemAt:). If you want to use collectionView(_:layout:sizeForItemAt:), change Estimate size to None in the storyboard.
https://stackoverflow.com/a/58369142/14351818
I am using
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 400, height: 600)
}
to specify my CollectionView's cell sizes. It works fine but as soon as I add a width constraint (UILabel.width == ContentView.width) to my UILabel inside the ContentView of the cell, the cell's width shrinks to the intrinsic width of the UILabel.
I am using UICollectionViewDelegateFlowLayout and horizontal scrolling.
How can I force the ContentView to stick to the cell size I specified and let the subviews follow the auto layout constraints?
The problem is that in the storyboard your collection view's Estimate Size is configured to Automatic:
You need to set it to None if you want your sizeForItemAt implementation to be obeyed rather than the internal constraints.
I have an application where I am using collectionview to display content which includes imageview, about 4 uilabels and a stackview which are all constrained to each other. This cell is scrollable vertically and not horizontally as I have to make provison for larger screen size like the iPad. The problem I have now is my CollectionViewFlowLayout height is static, How can I make it dynamic so that it resizes base on the height of the retuned content. the text of the label could vary so how do I handle this
below is how I have made my cell
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.size.width, height: 400)
}
further code would be added on request and any help is appritiated
I am creating a profile page screen for my application. The screen displays all the user's recent posts. I used storyboard to create two UICollectionViewCells in a UICollectionView, one that displays your profile info and the other that displays your posts. See this for how I designed it in storyboard: https://i.stack.imgur.com/6TzwK.png
When I run the application, I get the following result: https://i.stack.imgur.com/XmvY3.jpg
However, I desire the cells placed in a way that it looks like the following: https://i.stack.imgur.com/nWQ14.jpg
How do I force the cells the align so it looks like the image above? Thanks!
Found an answer to the question. Implement UICollectionViewDelegateFlowLayout delegate to your class. Then, include the following method into the class:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = UIScreen.main.bounds.width // get the width of the screen
let scale = (width / 3) // get the width (and height) of each cell
if indexPath.row != 0 { // check to see if the cell is the profile header
return CGSize(width: scale, height: scale) // if not, then return the cell size
}
return CGSize(width: width, height: ((238/414) * width)) // if it is the profile header, return the size for it.
}
Make sure "Min Spacing" for the UICollectionView's storyboard setting to 0,0. The cells will then align into a grid view.
I have an UICollectionView inside of an UIViewcontroller. I want to know how to set a maximum of cells in each row.
This question was asked before here: UICollectionView display 3 items per row
This is answered however in an Objective C. Therefore I can not understand the answer. Also, this is done programmatically. Is there a way to do this in the interface builder? Edit: 3 people reported this as a duplicate. Yes, of course it's a duplicated question, I literately already mentioned that. Again: the questions are given in Objective C which I can not read. Therefore the answer of this topic should differ from the the topic I already mentioned.
So this is the case. I want to know if its possible to display 3 items in a row. So if there are 4 items, the first row displays 3 cells and the second row displays the other cell. I tried it with autolayout, but this is not how it works I guess. The cell's size remains the same. This way the cell's size is the same on all devices. This is not what I want. The width and height of the cell should be proportional to the view's width and heights. Let say view.width * 0.25 and height view.height * 0.5.
Edit: I already tried this:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.size.width/4 - 0, height: collectionView.bounds.size.height/4 - 0)
}
And played with the number's (4 and 0) but not the result I wanted.
Edit: Found it out
Final answer: if you want to have 3 rows, and make sure minimal spacing is higher than 0:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.size.width/4 - 0, height: collectionView.bounds.size.height/1.5)
}