Image view added in collection view cell doesn't apply added constraints - ios

I've added an image to UICollectionViewCell and added constraints like the following image.
Constraints:
Width of ImageView = Width of Cell
Height of ImageView = Height of Cell
Align ImageView vertically in container (Cell)
Align ImageView horizontally in container (Cell)
I'm deciding the cell size at run time using the UICollectionViewDelegate method.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
// calculating cell size and returning it
}
Issue:
In the cellForItemAtIndexPath method, when I checked the cell size and image view size both have different values.
Cell {w:82.0, h:145.77}, ImageView {w:380.0,h:170}. Image has the same frame size which I set on storyboard. It is not adjusting based on the constraints.
Is there anyway I can ensure that it have the same size of my cell ?
Current Fix: (?)
cell.imageView.frame = cell.bounds
But it doesn't make any sense. Why I need to set the size explicitly, why the constraints not applied?

Check this answer by Marius Soutier: UICollectionView: different size items is not calculated on reused items
The comment below his answer is probably the solution you are looking for.
Basically, you have to call reloadData before you return your CGSize from sizeForItemAtIndexPath:.

Related

Adding UILabel/UIImageView to UIContentViewCell disturbs it's size

I have a UICollectionViewCell defined in storyboard which has a UILabel added to it's contentView. Collection view uses a flow layout and I return a fixed size of cell in flowlayout delegate as follows:
let sizeOfItem = CGFloat(210.0)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: sizeOfItem, height: sizeOfItem)
}
I added the following constraint for UILabel in storyboard and the cell automatically starts resizing itself to match the text size in UILabel. This is not what I want. I want the cell to be fixed size and label to autoshrink instead.
I even tried setting contentHuggingPriority of label to lowest value (i.e. 1). This stops the cell from auto-shrinking if the text in label is small. But still the cell grows when the text is big. I don't want this to happen either. I want the cell to be fixed size as returned by sizeForItem in delegate and the label to adapt it's font size.
EDIT: I also set contentCompressionProperty to lowest and it then works. But I am wondering what is the right way to fix this kind of scenario where contentView does not depend on subviews.
EDIT 2: The problem also appears when having UIImageView in contentView and the image is bigger or smaller than defined cell size. Setting intrinsic content size of UIImageView does not help.
To get the exact cell size as specified in the delegate method, you can't use an equal width constraint since then it will be a dynamic-size cell.

CollectionViewCell inside of presented ViewController in Xcode 11 distorting cell size

I have a UIViewController that I present from my main screen, which with Xcode 11 new presentation style, is dismissable by dragging down (modal style). Inside of this view controller there is a collection view with a full width and full height cell inside of which there is an imageView that occupies the whole cell.
My collectionView is meant to be paginated, and has a method sizeForItemAt to make the cell the size of the cell:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height)
}
What happens is that when I scroll past the collection view's content bounds, the cell get completely distorted and I get the following error:
The behavior of the UICollectionViewFlowLayout is not defined because the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
I have read a few posts about it, and I've tried a few things:
Presenting the UIViewController as full screen (it still distorts the cell when part the horizontal bounds of the collView)
Changing the content inset adjustment behavior of the collection view to ".never"
Removing the bounce
Taking out the image (it does work, as it doesn't distort the cell, but defeats the purpose of design)
Changed constraints of an image from equal to superview to equal height and width to cell and centered in the cell
I'm really racking my brain as to what can be going wrong, to the point that I might be thinking it might be a bug with Xcode 11's presentation style, however, I have no way to be sure of this.
What might be going wrong?

How to increase the UICollectionview Cell Size equal to Screen Size in swift 4.2?

How to increase the UICollectionView Cell width & height equal to screen in swift 4.2 ?
Provided your UICollectionViewCell has a subview of UIImageView that is anchored to fill it completely(i.e. UIImageView is anchored UICollectionViewCell in top, bottom, left and right manner).
The following method can be used to size the UICollectionViewCell in accordance to the screen screen holding it, this will automatically result in the UIImageView being as big as the screen itself.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.collectionView.bounds.size //to ensure that this works as intended set self.collectionView size be the screen size.
}
Please note that the UICollectionView is big enough to hold the size of the UICollectionViewCell that you seek.
You need to change your cell size to fit the collectionview. Add this in viewDidLoad
if let flow = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
flow.itemSize = self.collectionView.frame.size
}

Swift auto layout in UICollectionView with intrinsic height of cells

I'm having a hard time with auto layout and UICollectionView. I have a vertical UICollectionVIewFlowLayout that contains two different types of cells, as in the image below:
The SingleCard cell contains a subview with an image (UIImageView). The HorizList cell contains a subview which is a horizontal UICollectionView (a list of thumbnail photos). The heights of the two cell types are as follows:
SingleCard: the width of the cell shall be the same as the screen width. The height shall be dynamic to the height of the UIImageView (to keep proportions of the image and have it fill screen width no matter of device size)
HorizList: the height is constant, say 200 points.
My attempt, in the CollectionViewController is to do
override func viewDidLoad() {
...
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.estimatedItemSize = CGSize(width: 200.0, height: 235.0)
}
This I do to get the two cell's intrinsic size to apply. Then I do not implement
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
at all.
My question is, what do I implement in
override var intrinsicContentSize: CGSize {
??
}
for the two different cell types? Maybe this is not the only thing I need to do, if so I'm grateful for additional hints.
Thanks!
/ola

UICollection View causes "UICollectionViewFlowLayoutBreakForInvalidSizes" on smaller devices

On an iPhone 6 Plus, the collection view cells are fine, but when testing on another device size like the iPhone 5, i'm bombarded with "
017-06-15 01:59:25.744 HyperTest[3865:8825385] The behavior of the UICollectionViewFlowLayout is not defined because:
2017-06-15 01:59:25.744 HyperTest[3865:8825385] the item width must be less than the width of the UICollectionView minus the section insets left and right values, minus the content insets left and right values.
2017-06-15 01:59:25.745 HyperTest[3865:8825385] The relevant UICollectionViewFlowLayout instance is , and it is attached to ; layer = ; contentOffset: {0, 0}; contentSize: {414, 219}> collection view layout: .
2017-06-15 01:59:25.745 HyperTest[3865:8825385] Make a symbolic breakpoint at UICollectionViewFlowLayoutBreakForInvalidSizes to catch this in the debugger.
especially when I do this:
let layout = billFeedCollectionView.collectionViewLayout as? UICollectionViewFlowLayout // casting is required because UICollectionViewLayout doesn't offer header pin. It's feature of UICollectionViewFlowLayout
layout?.sectionHeadersPinToVisibleBounds = true
layout?.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
anyway, I can resolve this problem? I need to ensure that the cell scales and fits all devices.
By confirming UICollectionViewDelegate from your class. The delegate method sizeForItemAtIndexPath will call from UICollectionViewDelegateFlowLayout and this will call in your class now you can return the size of UICollectionViewCell.
This works for me
method:
collectionView.delegate = self
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(collectionView.frame.size.width, collectionView.frame.size.height)
}
It's also possible that when you have a collectionView in a UITableViewCell this cell actually resizes the collectionView height to 0.
In my case, the collectionView is showing an array of UIImageView to display some image gallery in each cell.
If the cell is not supposed to show any images (text without image for example), the collectionView is hidden.
The collectionView, if put within a StackView might need to have a height constraint and to avoid conflicts, you might need to set it to priority 999.
Then, when you hide the collectionView, it will actually try to set the height to 0.
The collectionView can still contain images in it and that will trigger the error.
SOLUTION: empty your datasource and reload the collectionView when you configure your cell.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let cellsize = CGSize(width: (CollectionView.bounds.size.width/2) - 12, height:(CollectionView.bounds.size.height/3) - 20)
return cellsize
}
here CollectionView is outlet of UICollectionView

Resources