I'm developing an app with xcode/swift and the constraints that i put are only working for one screen size.
I looked for solutions, i saw things involving auto-layout but nothing has worked for me.
What i Want
What i have when i change the screen format
Can someone please help me, what is the best solution to have the layout adapt itself to the different screen resolutions ?
Thank you
The best solution in your case is to use UICollectionView, create one UICollectionViewCell with label and change background according to your data. Then, set your UIViewController as delegateFlowLayout, which has method:
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
Here you can calculate size for your according to screen size. UIScreen.main.bounds.size returns CGSize which is size of the screen.
Delegate methods can be used to set inter item and line spacing between cells.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
Guide from Apple about collection view.
Related
I am using a collection view in a storyboard and I need one ribbon with an image in the center of the screen. Constraints work fine on iPhone, but not iPad. How can this be done?
The collectionView cell size is not specified for different screen sizes.
Use UICollectionViewDelegateFlowLayout's method
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
https://developer.apple.com/documentation/uikit/uicollectionviewdelegateflowlayout/1617708-collectionview
The code to set the width and height of the collectionView's cell is as following:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width/6, height: collectionView.frame.width/5)
}
When the Simulator is vertical before running the scheme, then we get
and
But when the Simulator is horizontal before running the scheme, we get
and
The size of cells will change as the Simulator's initial state. I think the reason is that collectionView.frame.width depends on the Simulator's state.
How to fix the cell's size using auto layout like the code before regardless the ipad's initial state?
Best and easiest way to get through this is to make it a sqaure rather than a Rectangle . basically have the same value to width/height in my opinion . If it doesnt help you try to below and one small change to your code is to use the bounds instead of the frames .
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width/5, height: collectionView.bounds.width/5)
}
also if you could guess a size margin in betweens you could also reduce that bounds.width/5 -10
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let standardWidth = max(collectionView.frame.width, collectionView.frame.height)
return CGSize(width: standardWidth/5, height: standardWidth/5)
}
This simple solution works well.
Trying to create a custom cell but when I am adding label in the cell collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) doesn't work.
Without label cell UI:
and the iPad simulator UI is:
But when I am adding label into the cell:
The iPad Simulator UI becomes :
In UICollectionViewDelegateFlowLayout in the method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let emptySpace = 87*2 + 10
let remainingWidth = Int(self.view.frame.width) - emptySpace
return CGSize(width: remainingWidth/2, height: remainingWidth/2)
}
Are you building with Xcode 11 (GM 2)? I had similar issues implementing sizeForItemAt.
It seems something is causing the collection views to disregard the size returned in sizeForItemAt and instead use the size of the child views.
What worked for me is setting Estimate Size to None on the collection view in Interface Builder.
This is not ideal, especially if you have many cells, but it was the only fix I found unfortunately.
Normally I just use this function:
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat
to set some spacing between the items in a collectionView, but the spacing is the same for all items. I would like to set the spacing to be different between some items, depending on some logic that I need to check, the logic will depend on which cell is before and after, so I would need something like IndexPath to check that.
When we want to set size of a cell, we conveniently get IndexPath from the function below, but not from the function above.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
What can I do to achieve this?
There's no good way to do it without creating your own layout. There's too much to it to go into it here, but there's tons of good tutorials on the matter. Here's a good place to start.
I have a UICollectionView in my app. I want it to constrain so it only has two cells on each horizontal row. For iPhone classes I achieve this by setting the width so three cells can't fit in the same horizontal row. This seems to be a fix but I don't know how to resize the cell for iPads. I have heard to use:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
but I can't access this function. Does Swift no longer support this function anymore?
Question: Can I force my screen to only display 2 cells on each horizontal row?
You should first conform to protocol UICollectionViewDelegateFlowLayout
and then implement the method :
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.size.width * 0.5, height: 30)
}