UIcollectionview with 2 different kind of cells - ios

I need to create a UIcollectionview with grids of cells with 3 cells per row. After a certain amount of cells, lets say 60, I need to display a big cell with image view inside of it, and the cells needs to be in full width of the UIcollectionview.
I have done created the 3 cells part, but I failed to figure out how to insert the big image cell and how to layout it properly.
Thanks.

How about you do a few sections? And the header is the other cell. You can put an image there as well.

You could specify the size of the cell in the UICollectionViewFlowLayout delegate method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
//logic to find if the cell is 60 th item and then and dont forget to return the size of the other cells.
if 60th cell {
return size
} else {
return size
}
}

Related

UIcollectionview Update cell height

Currently I am working on one dynamic layout of collection view.
On certain clicks inside collectionview cell (ex cell has UIbutton) the cell of that click button should increase height.
i have implemented the method of collectionviewflowlayoutdelegate
SizeforItemAt:
When cell button click i am just reloading particular one indexpath
self.collectionview.reloadItems([indexpath])
It will call SizeforItemAt: but it is calling for all cell again. So due to this my collectionview jerking all cells as it’s sizes are updating.
So is there any way to update height for single cell only?
You can do like this
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
let width = collectionView.bounds.width
let height = 0.0
// for specific cell height
if indexPath.row == 1{
height = 200.0 // chnage height for a specific cell
}else{
height = collectionView.bounds.height //actual height
}
return CGSize(width: width, height: width)
}
Update
I am not sure will it work or not when clicking on the button.
But you can change the height of a specific cell that is selected by implementing didSelectItemAt like the below.
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.performBatchUpdates(nil, completion: nil)
// to reload specific cell use below line.
//collectionView.reloadItemsAtIndexPaths([indexPath])
}
You can Check if the idexPath in sizeForItemAt is selected or not. if it is selected then you can change the height otherwise return the original height. like the following.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
switch collectionView.indexPathsForSelectedItems?.first {
case .some(indexPath):
let height = 200.0 // here you can change the height for selected cell.
return CGSize(width: view.frame.width,height: height)
default:
let height = 200.0 // standard height
return CGSize(width: view.frame.width, height: height)
}
}
Check for collection view cell dynamic height.
And do not hard code height for cell, instead make the components inside the cell define the height of the cell. In this way when tap on button pragmatically increase/decrease the size of some component inside that cell and you would get the desired result.
So is there any way to update height for single cell only?
No. If sizeForItemAt: is implemented, it can and will be called for any cells the runtime wishes. It isn't up to you what cell this is. Your job is to return the correct value for whatever the cell in question is. If you don't want to change a cell's height, don't change it, but you can't stop the call from arriving.
However, I doubt that this has anything to do with your issue. It sounds like what you want is to update the height of this one cell is a smooth (animated) manner. That has nothing to do with what you asked.

Problem with custom tableview cell . Collectionview inside the custom tableview cell is not adjusting according th the height of cell

In the tableview i have a custom cell(which has a height of 500 in interface builder).Within that cell i have a collection view which i'm pinning to edges by (10,10,10,10) .But in tableview delegate method heightForCell: atIndexPath: I'm giving the height as 200.
In the output i'm getting the cell height as 200 but the collectionview inside that cell is not rendering layouts according to 200(Which i took in code) but by 500(which i took in interface builder) taking height given in interface builder
you have to using delegate like tableview to change collection cell height
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 200, height: 200)
}

Collection View Cell Size/Fitting issue

I am working on an iOS app in swift 4. I have implemented collection view and there are two cells at the front as shown in the image:
When I run my app on bigger screen sizes like iPhone 6/7/8 Plus, then it Shows two complete cells with one-half cell. What I want to achieve is that it shows two cells in front of every screen size, Please help.
Implement the UICollectionViewDelegateFlowLayout protocol in your ViewController, then implement:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSize = //calculate cell size based on the width of the view and padding between cells
return cellSize
}
Check out the documentation for the UICollectionViewDelegateFlowLayout and implement its methods to modify the spacing between the cells.

Swift iOS -How to Truncate Horizontal CollectionView Cells when they are about to go past Screen Bounds

I have a collectionView cell that displays the cells horizontally. I only want a set number of cells to show on the screen and after the amount I want to display ... or something to signify there are more cells available. I don't want the user to scroll to more cells
Because there are different screen sizes like iPhone 4/5/6/7/iPad etc.. I don't want to put an exact number of items to get displayed. Instead I want to to truncate the amount of items based on the screen size for eg. On an iPhone 7+ in .compact size class at least five cells can fit on the screen but on an iPhone 4 only three cells can fit on a screen and on an iPad probably 20 cells.
I imagine I'd do something like this:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//I know this is comparing an Int to a CGRect and it won't work
if items.count > UIScreen.main.bounds.width{
//stop count and display truncation dots ...
}
return self.items.count
}
How would I accomplish this?
To accomplish that you need to implement the protocol method
collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
You need to manually return the size of each cell so in this case you will calculate the width of the cell depending on your screen size.

UICollectionView: dynamic cell heights with UIStackView

I have a storyboard, consisting of a single UICollectionView with multiple cells, each of varying height. The first cell takes the height from the UICollectionViewDelegateFlowLayout:
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
.. but I'd like the second cell to be shorter.
I've placed two UIStackViews inside a "master" UIStackView inside the cell, and each of the inner UIStackViews has one or more labels, like this:
cell
--> stackView (master)
--> stackView (1)
--> label
--> stackView (2)
--> label
--> label (etc)
.. in the hope that the UIStackView would make the cell height dynamic, but it doesn't. It takes the height from the UICollectionViewDelegateFlowLayout as before.
How should I be doing this?
You need to compute the size of the content for the CollectionViewCell and return it to the sizeForItemAt function.
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
// Create an instance of the `FooCollectionViewCell`, either from nib file or from code.
// Here we assume `FooCollectionViewCell` is created from a FooCollectionViewCell.xib
let cell: FooCollectionViewCell = UINib(nibName: "FooCollectionViewCell", bundle: nil)
.instantiate(withOwner: nil, options: nil)
.first as! FooCollectionViewCell
// Configure the data for your `FooCollectionViewCell`
cell.stackView.addArrangedSubview(/*view1*/)
cell.stackView.addArrangedSubview(/*view2*/)
// Layout the collection view cell
cell.setNeedsLayout()
cell.layoutSubviews()
// Calculate the height of the collection view based on the content
let size = cell.contentView.systemLayoutSizeFitting(
CGSize(width: collectionView.bounds.width, height: 0),
withHorizontalFittingPriority: UILayoutPriorityRequired,
verticalFittingPriority: UILayoutPriorityFittingSizeLevel)
return size
}
With this, you will have a dynamic cell heights UICollectionView.
Further notes:
for configuration of the collection view cell, you can create a helper function func configure(someData: SomeData) on FooCollectionViewCell so that the code could be shared between the cellForItemAt function and sizeForItemAt function.
// Configure the data for your `FooCollectionViewCell`
cell.stackView.addArrangedSubview(/*view1*/)
cell.stackView.addArrangedSubview(/*view2*/)
For these two lines of code, it seems only needed if the UICollectionViewCell contains vertical UIStackView as subViews (likely a bug from Apple).
// Layout the collection view cell
cell.setNeedsLayout()
cell.layoutSubviews()
If you'd like to change the height of your cells you're going to have to change the height you return in the sizeForItemAtIndexPath. The stack views aren't going to have any effect here. Here's an example of what you can do:
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if indexPath.row == 1 {
return CGSizeMake(width, height/2)
}
return CGSizeMake(width, height)
}
This will change the size of your cells at row 1. You can also use indexPath.section to choose sections. Hope this helps.

Resources