I have a UICollectionView with horizontal scroll and variable sized items.
Is it possible to have constant spacing between items in 'horizontal' rows?
Thanks.
You need to provide cell's variable width. Implement this method from UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = (items[indexPath.item] as NSString).size(attributes: nil)
return CGSize(width: size.width + yourTextPadding, height: yourCellHeight)
}
You can also provide label's font attributes for exact computation or just use some constant (like 2 times width of text).
Related
I have a UICollectionView with a custom cell, however, I am trying to impose constraints on the UICollectionView, so it is always half the width of the screen and half the height of the screen. The one issue I continually encounter is that while the UICollectionView changes according to what device the app is deployed on, the UICollectionViewCells hold the exact same pixel width and height dimensions. This is the code I have tried to implement to make each cell the same height and width as the CollectionView.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.frame.height
let width = collectionView.frame.width
return CGSize(width: width, height: height)
}
This code, however, doesn't work as the size of the cells are simply the values that are specified in the size inspector for the UICollectionView.
I'm unable to figure out what I am doing wrong here with my code. Thank you very much in advance for your help.
The issue is your collection view cell size is fixed always. So the cell size is not adjust according to screen size.Use view frame size.(remove values from size inspector)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
I have a UICollectionView and I have implemented the delegate to calculate the width of my cells for 0 spacing between cells.
It works great on its own, but when I have it inside a container view less than the size of the device, iOS incorrectly works out the spacing between the cells adding a horizontal space I don't want.
I have verified the width I am using to calculate the cell size is correct, so I'm not sure what is causing the problem.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let widthPerItem = view.frame.width / itemsPerRow
return CGSize(width: widthPerItem, height: 60)
}
You are calculating your cell size based upon the size of the view. Since the collectionView doesn't take up the full width of the screen, you are getting the incorrect value. Instead, you should base your calculation on the width of the collectionView itself.
Use the bounds of the collectionView instead of the frame of the view:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let widthPerItem = collectionView.bounds.width / itemsPerRow
return CGSize(width: widthPerItem, height: 60)
}
Ok, the problem was actually related to my uicollectionviewcontroller not correctly sizing to it's parent container view. Changing to a uiviewcontroller with an embedded uicollectionview plus constraints fixed the problem.
I'm using this method below in my UICollectionView to stretch/fill the cell, but it seems like it's constraining to the margins. It's stopping like 10 px shy of the edges. I basically want to set the constraints of the cell to "0" and "0" to fill the width completely and NOT constrained to the margins.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let customHeight = CGFloat(116)
return CGSize(width: collectionView.frame.size.width, height: customHeight)
I have a UICollectionView with a reusable header (that's why I'm using collection and not tableview). The cell needs to have a variable height, depending on a UILabel. I know in UITableView you can use UITableViewAutomaticDimension to auto resize the cell, but I can't find an analogous function for UICollectionView. Any idea? I suppose I should start with sizeForItemAtIndexPath ?
override func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let height = // needs to be variable
let width = UIScreen.mainScreen().bounds.width
return CGSize(width: width, height: height)
}
Setup the cell with auto layout constraints then set the estimatedItemSize property of the your UICollectionView's UICollectionViewFlowLayout. For example:
self.collectionView.collectionViewLayout.estimatedItemSize = CGSize(100,100)
I'm designing the UI of an ios 8 app being built in swift. I have intermediate knowledge of autolayout and constraints. Here's my situation: I have a custom collection view controller and collection view cell. I want to use the "equal widths" and "equal heights" constraints within interface builder to set the width and height of a cell relative to a multiplier of the parent view-- as opposed to using intrinsic height/width properties such as 320 x 94.
Here's what I tried
using intrinsic width and height for size classes within IB. (This doesn't work)
Control-Dragging from a UICollectionViewCell to the CollectionView (didn't work seeing as "equal heights " and "equal widths" are not even constraint options)
Should I just settle for the intrinsic height and width and assume that CollectionViewFlowLayout will take care of me or is there a way to do this programatically?
Thanks.
Alex
Use the UICollectionViewDelegateFlowLayout methods to tune your cell size
for example if you want 3 cells across the view width
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
let width = CGRectGetWidth(collectionView.bounds)
let hcount = 3
let gapcount = CGFloat(hcount) + 1
//this should be a class var/constant which you can feed into the minimumLineSpacingForSectionAtIndex delegate
let gap = 10
let kwidth = width - gap
let keywidth = kwidth/CGFloat(hcount)
return CGSize(width:keywidth,height:50)
}
You can tune the distance between the cells with
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat
and the edge insets with
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
Layout and size of cells is done by the collectionViewLayout property of collectionView. Using a collectionViewLayout of class UICollectionViewFlowLayout, you can set fixed size using item size property:
(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize = 100 //set fixed size here
or set variable size using delegate method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// determine variable size here using indexPath value
}