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
I need to have a view controller that has a scroll in view.
The problem is that I need that both scrolls (of scrollView and collectionView) work together.
But when I add ScrollView in all frame, nothing works...
That's an image that shows what I want:
And when I scroll viewController, all content scroll together..
Someone know a good way to implement this in swift 4?
Thanks in advance.
I've seen this done many ways. The most popular of which is to have these views embedded in a UITableView.
You can set the first cell height to a proportional amount to the superview, while keeping another cell that will contain your CollectionView. You would be able to take advantage of the UITableView's scrollView as well as it's memory efficiency and delegate.
A better way to do this is to use the scroll direction in UICollectionViewDelagateFlowLayout. Just add the UICollectionViewDelegateFlowLayout protocol or extends your ViewController to it. Then use .scrollDirection in the section of your UICollectionView.
And sample declaration like this
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .vertical //or .horizontal depends on your liking
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
...//
return cv
}()
then add to your view view.addSubview(collectionView)
More info in the apple doc or jump to definition
I have a collectionView that scrolls vertically. Inside the cells of that collectionView is another collectionView that I have a custom layout for. The layout is currently a subclass of UICollectionViewFlowLayout and I want the scroll direction to be horizontal. I have tried a variety of ways to set the scrollDirection to horizontal but none of them are working. How do I set scroll direction on a subclass of FlowLayout?
You can easily change scroll direction by this code:
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
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?
I would like to achieve this result:
Searching around I found out that probably the way to do it is using UICollectionView, so no problem with that since there are many tutorials and questions on Stack Overflow. I have 3 questions:
I cannot find anything about the "separators" (the line that divides all the boxes). I like that it doesn't touch the screen borders horizontally. Is it done programmatically?
To divide the space equally in all devices (3 boxes/buttons horizontally) I found this answer answer. Is this the right approach?
For the Blur effect I found this answer: How to implement UIVisualEffectView in UITableView with adaptive segues
For a TableView it would be:
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
tableView.backgroundColor = UIColor.clearColor()
let blurEffect = UIBlurEffect(style: .Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
tableView.backgroundView = blurEffectView
}
Can I do something like this?
#IBOutlet var collectionView: UICollectionView!
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
collectionView.backgroundColor = UIColor.clearColor()
let blurEffect = UIBlurEffect(style: .Light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
collectionView.backgroundView = blurEffectView
}
Create the UICollectionViewController like this in a file that sub-classes from UICollectionViewController:
convenience override init() {
var layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.itemSize = CGSizeMake(<width>, <height>)
// Setting the space between cells
layout.minimumInteritemSpacing = <Space between columns>
layout.minimumLineSpacing = <Space between rows>
return (self.init(collectionViewLayout: layout))
}
In the viewDidLoad you an set the background color like this:
self.collectionView.backgroundColor = UIColor.orangeColor()
My guess is you can set a background image like this:
self.collectionView?.backgroundColor = UIColor(patternImage: UIImage(named: "image.png")!)
The blur effect that you found looks good. I am having trouble figuring out how it would work though. Probably set it using the backgroundView property.
I'll update if I find the answer.
Update:
Here is an idea of something that might work for blurring the cells.
Create a cocoa-touch class that sub-classes from UICollectionViewCell, then add this code to it:
convenience override init(frame: CGRect) {
self.init(frame: frame)
var blurEffect: UIVisualEffect
blurEffect = UIBlurEffect(style: .Light)
var visualEffectView: UIVisualEffectView
visualEffectView = UIVisualEffectView(effect: blurEffect)
visualEffectView.frame = self.maskView!.bounds
self.addSubview(visualEffectView)
}
override func layoutSubviews() {
super.layoutSubviews()
self.maskView!.frame = self.contentView.bounds
}
Then in the CollectionViewController file, in the viewDidLoad, change this line of code:
self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
Change UICollectionViewCell.self to <Name of CollectionViewCell file>.self
Result:
1) First of all, I think you need to change how you look at that layout. There are no separators. Just UICollectionView Cells with spacing between cells, lowered opacity and some blur.
This settings will give you something close to image you posted, you can edit it for your needs later:
On storyboard go to your UICollectionView's size inspector.
Min Spacing-> For Cells = 2, For Lines = 2.
Section Insets-> Left = 7, Right = 7.
2) I'm using this on my app to divide space equally for 3 cells. Changed it for your settings. Just copy/paste and you are good to go.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let screenSize: CGRect = UIScreen.mainScreen().bounds
let screenWidth = screenSize.width
return CGSize(width: (screenWidth/3)-6, height: (screenWidth/3)-6);
}
}
And as the last step put two images on top of CollectionView, to the left and right of the view and make widths equal to 7 and heights equal to UICollectionView. These images should have same opacity/background with cells. This will make it look like the image you want.
I hope my answer works for you. Good luck.
The first thing I would like to say is, your all above result can be achieved from UICollectionViewFlowLayout, Which is the default layout for UICollectionView.
UICollectionViewDelegateFlowLayout has all of the methods that can fulfill your requirements.
The flowLayout has minimumLineSpacingForSectionAtIndex and minimumInteritemSpacingForSectionAtIndexfor giving the spacing between the cells(both horizontally and vertically).
Its not a good way of giving cell frame in cellForItemAtIndexPath (like you submit the answer link). For that flowLayout provides a delegate for sizing cell sizeForItemAtIndexPath.
About the third question, yes you can use UIVisualEffectView for bluring purpose but compatible for only after iOS 8 and has issue with iPad2 I guess. But for your problem I would blur each cell rather than collectionView itself(since cell spacing is not blur).
I cannot find anything about the "separators" (the line that divides all the boxes). I like that it doesn't touch the screen borders horizontally. Is it done programmatically?
Yes, it looks like it is rendered on to a layer. You should read the Quartz 2D Programming Guide to get a handle on drawing and working with layers.
To divide the space equally in all devices (3 boxes/buttons horizontally) I found this answer answer. Is this the right approach?
This would be an option, but would not give you the separators look you like from your screen shot.
I would have my cell view's backgroundColor is set to clearColor, and then set the UICollectionView's backgroundView property to a view containing your separators and the blur effect. Make sure the UICollectionView's backgroundColor property is set to clearColor.
About the third question, yes you can use UIVisualEffectView for bluring purpose but compatible for only after iOS 8 and has issue with iPad2 I guess. But for your problem I would blur each cell rather than collectionView itself(since cell spacing is not blur).
If you use the backgroundView property of the UICollectionView to handle your separators and blur then your cells would only need to have their backgroundColor set to clearColor.
You should note that there is more than one way to do this, each way will have it's own drawbacks choose what works for you best.
I have created this meethod for custom layout. You can use by modifying according to your request.
func setCollectionLayout() {
let layout:UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top:0,left:0,bottom:0,right:0)
layout.itemSize = CGSize(width: UIScreen.main.bounds.size.width/2 - 1, height: 136)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
collectionView.collectionViewLayout = layout
}