UICollectionView AutoLayout max width? - ios

I'm having a dilemma maybe someone can help. I followed this tutorial that showed me how to dynamically adjust the height of a collectionview to match the height of the text.
https://possiblemobile.com/2016/02/sizing-uicollectionviewcell-fit-multiline-uilabel/
if let flowLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSizeMake(1, 1) }
cell.label.preferredMaxLayoutWidth = 50
But the issue I'm having is now the collection view wraps around the text instead of conforming to collectionView.bounds.width. So when i have text that is smaller than the collectionview width, the cell wraps around the text. I want the cell to match the height of the text but have a set width set to collectionview bounds. How could I achieve this?

Related

UICollectionViewCell not aligning properly when multiple cells added

I have a UICollectionViewCell in a UICollectionView configured with a UIImage and UILabel. I am trying to add multiple rows of the cell and have defined it to have 3 cells per row. However, the second cell that renders is aligned on the right side of the view and it just starts goes to the next row instead.
My Storyboard:
When I add multiple cells:
I have tried setting up custom layout sizing but I am still running into the same issue where the second cell is right aligned which messes up the entire layout.
let collectionViewWidth = collectionView.frame.width
let itemWidth = (collectionViewWidth-leftAndRightPaddings)/numberOfItemsPerRow
let itemHeight = (8*itemWidth)/6
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: itemWidth, height: itemHeight)
Not sure where I am going wrong here.
I was able to get this one solved. The issue was the spacing between the cells which was messing up the alignment. Adding these two lines did the trick:
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

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
}

UICollectionView horizontal columns with vertical scroll

I'm trying to get a UICollectionView to display horizontal columns when on iPad.
This is my current layout when on iPhone (Collection view scrolls vertically):
Each UICollectionViewCell has a dynamic height depending on the content but the width is set to 100% of the screen width.
The cell height is set like this:
if let flowLayout = collectionView?.collectionViewLayout
as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = CGSize(width: 1, height: 1)
}
It's a standard UICollectionView using the usual dataSource/delegate methods (sizeForItemAtIndexPath, cellForItemAtIndexPath etc.)
When on iPad, I'm adjusting the width depending on the number of columns required:
var numberOfColumns = 1
if screenWidth > 760 {
numberOfColumns = 2
}
let cellWidth = screenWidth/numberOfColumns
Adjusting the width of the columns gives me this:
But i'm trying to get something like this:
Is there a way to achieve this using UICollectionView?
A few notes about the collection view:
Layout is set to Flow
Scroll direction is vertical
Headers are a fixed height
Cell height is dynamic based on content
I need the collection view to scroll vertically if the content extends outside of the screen

Sending heightForRow:atIndexPath height value after calculating it in-cell

I have a UITableView that has few cells with different heights. Each row's is dynamically adjusted according to the content it contains.
I have a custom UITableViewCell with a UICollectionView in it that should be resized according to how many cells it has (all the cells should be visible, without inside scrolling).
I also have a UITableViewCell with another UITableView that should be resized according to how many cells it has (all the cells should be visible, without inside scrolling).
The problem is that I don't have the contentSize of the collectionView and the tableView while heightForRow:atIndexPath gets called so I can't set the values to something right.
I've tried to set it to UITableViewAutomaticDimension and to set the cell.contentView.frame.size.height to the contentSize when it got set (added an observer on "contentSize") but then the cells were on top of each other (the collectionView was ontop of the tableView instead of above it).
The tableView code is a regular tableView code.
The collectionView code is:
self.collectionView.collectionViewLayout = UICollectionViewLeftAlignedLayout()
let collectionViewFlowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
collectionViewFlowLayout.estimatedItemSize = CGSize(width: 34, height: 50)
What is the best way to adjust the size of the tableView and the collectionView?
Thank you!
You can just ask UITableView to adjust its cell height again with this piece of code:
self.tableView.beginUpdates()
self.tableView.endUpdates()

UITableViewCell dynamic row height + custom UIView + Auto Layout

I am trying to get a custom photo container with multiple UIImageViews to fit in my tableview cell. The view contains a variable number of images (1 ~ 9), and its height would change correspondingly from 1x to 3x imageHeight.
I used AutoLayout to define the top/bottom/leading/trailing margins with the tableview and the custom UIView inside, and to enable self-sizing cells, I have set
tableView.estimatedRowHeight = X
tableView.rowHeight = UITableViewAutomaticDimension
I initialize these cells with
tableView.register(nib: forCellReuseIdentifier:)
and in tableView(_ tableView: cellForRowAt:) method, I setup the cell with:
let cell = tableView.dequeueReusableCell(
withIdentifier: "test9cell",
for: indexPath) as! SocialFeedTableViewCell
cell.photoContainer.setup(with: urls)
cell.photoContainer.loadImages()
return cell
where setup() hooks each imageView in the container with a URL
func setup(with urls: [URL]) {
self.imageUrls = urls
for i in 0 ..< urls.count {
let imageView = UIImageView(frame: CGRect.zero)
self.addSubview(imageView)
self.imageViews.append(imageView)
}
self.setNeedsLayout()
}
func loadImages() {
self.imageViews.forEach { imageView in
imageView.frame = // Calculate position for each subview
imageView.sd_setImage(...) // Load web image asynchronously
}
}
Defining intrinsicContentSize for the view:
override var intrinsicContentSize {
let frameWidth = self.frame.size.width
var frameHeight: CGFloat
switch self.imageUrls.count { // range from 1...9
case 1...3:
frameHeight = frameWidth / 3
case 4...6:
frameHeight = frameWidth / 3 * 2
default:
frameHeight = frameWidth
return CGSize(frameWidth, frameHeight)
}
override func layoutSubviews() {
super.layoutSubviews()
self.imageViews.forEach { imageView in
imageView.frame = // Calculate position for each subview
}
}
The problem here is: after I set the initial intrinsicContentSize, the container's frame size changes in layoutSubviews() afterwards. Although by then I can position the imageView subviews correctly, the cell height will not be changed anymore.
Hope I am not making this problem more confusing. Could someone point out how would I resize the cell height AFTER modifying the contents of its UIView subview? Thanks!
There are a few things here that will be causing you some issues with dynamically sized cells.
You are adding multiple items to the cell but are not defining any auto layout constraints on the image views, so it does not know how to properly place / stack the items.
from the code above you are adding UIImageView with a frame of CGRectZero, without autulayout rules they will either stay zero or try to adjust to the contentsize when you add an image, but they wont adjust the cells height.
If you are loading images from the network they will likely be added/rendered after the tableviewcell has done its initial rendering. So you will likely need to cache the loaded images and reload the cell so that they can load in at the right time.
Now this last point is alot more complicated.
Dynamic UITableViewCell's calculate their height based on the autolayout rules of the content within them. You MUST have enough constraints from your content to the UITableViewCell's contentView property (to all edges) that give the cell enough information to place each item, calculate its overall height and width and therefore it is able to calculate the new height.
Using just one image isn't too bad for dynamic sized cells. but placing multiple items dynamically without any rules after the cell has initially rendered will not work.
You need to decide how these images should be laid out in your cell. once you have this you can look at adding the required constraints as you add the image views. Personally I would only add the image views once i have received each image.
Previously when I have done this I have cached the images once received and re-loaded the cell so that the image can be placed in the cell as it is rendered, allowing the tableview cell to calculate its height based off the image dimensions and constraints.
You may want to also consider using a collection view or merging the images together into a single image and using that in your cell. You could do this on device at runtime or server side if you have that kind of access to the images.

Resources