Connecting Custom layout class to collection view in code
Connecting Custom layout class to collection view in code
i have a small question about a custom layout class and i need to connect it to my collection view in code not by the story board because i create the whole project by code . any help, please ?
my main class
import UIKit
import Firebase
class UserProfileController: UICollectionViewController
override func viewDidLoad()
super.viewDidLoad()
collectionView?.backgroundColor = .white
//fetchUser()
collectionView?.dataSource = self
collectionView?.delegate = self
collectionView?.register(TestCell.self, forCellWithReuseIdentifier: mainCellId)
fileprivate let mainCellId = "mainCellId"
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: mainCellId, for: indexPath) as! TestCell
return cell
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return 15
override func numberOfSections(in collectionView: UICollectionView) -> Int
return 1
the custom layout class which need to connect it to the collection view in code not story board
import UIKit
struct UltraVisualLayoutConstants
struct Cell
static let standardHeight: CGFloat = 100
static let featuredHeight: CGFloat = 280
// static let standardWidth: CGFloat = 100
// static let featuredWidth: CGFloat = 280
class UltraVisualLayout: UICollectionViewLayout {
// amount which users need to scroll before featured cell changes
let dragOffset: CGFloat = 180.0
var cache = [UICollectionViewLayoutAttributes]()
//return item index of current featured cell
var featuredItemIndex: Int
get
//use max to ensure that featureditemindex never be < 0
return max(0 , Int(collectionView!.contentOffset.y / dragOffset))
// returns value between 0 and 1 to represent how close the next cell becomes the featured cell
var nextItemPercentegeOffset: CGFloat
get
return (collectionView!.contentOffset.y / dragOffset) - CGFloat(featuredItemIndex)
// return the width of collection view
var width: CGFloat
get
guard let width = collectionView?.bounds.width else return 0
return width
// return the height of collection view
var height: CGFloat
get
guard let height = collectionView?.bounds.height else return 0
return height
//returns the number of items in the collection view
var numberOfItems: Int
get
return collectionView!.numberOfItems(inSection: 0)
// MARK: UICollectionViewLayout
// return the size of all content in collection view
override var collectionViewContentSize: CGSize
let contentHeight = (CGFloat(numberOfItems) * dragOffset) + (height - dragOffset)
return CGSize(width: width, height: contentHeight)
override func prepare()
cache.removeAll(keepingCapacity: false)
let standardHeight = UltraVisualLayoutConstants.Cell.standardHeight
let featuredHeight = UltraVisualLayoutConstants.Cell.featuredHeight
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
var y: CGFloat = 0
for item in 0..<numberOfItems
let indexPath = NSIndexPath(item: item, section: 0)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
attributes.zIndex = item
var height = standardHeight
if indexPath.item == featuredItemIndex
let yOffset = standardHeight * nextItemPercentegeOffset
y = collectionView!.contentOffset.y - yOffset
height = featuredHeight
else if indexPath.item == (featuredItemIndex + 1) && indexPath.item != numberOfItems
let maxY = y + standardHeight
height = standardHeight + max((featuredHeight - standardHeight) * nextItemPercentegeOffset, 0)
y = maxY - height
frame = CGRect(x: 0, y: y, width: width, height: height)
attributes.frame = frame
cache.append(attributes)
y = frame.maxY
// return all attributes in cache whose frame intersects with the rect passed to the method
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
var layoutAttributes = [UICollectionViewLayoutAttributes]()
for attributes in cache
if attributes.frame.intersects(rect)
layoutAttributes.append(attributes)
return layoutAttributes
// return true so that layout is continuously invalidated as the user scrolls
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool
return true
sry for that , i edited it @Chris Edgington
– Ahmed Seddek
Aug 23 at 15:38
1 Answer
1
You cannot set the layout programmatically if you don't have an initializer. From the docs:
layout
The layout object to use for organizing items. The collection
view stores a strong reference to the specified object. Must not be
nil.
Since you seem to be using the storyboard, you'll have to set it there.
Once you create you layout class in code, it will show up when you click you collection view on the storyboard. The default layout will be set to Flow, when you change it to Custom, a new class field will show up. When you click that, it will list your layout class. You can choose it and set it from there.
However if you are initializing your storyboard programmatically, then you just need to pass it as a parameter to your initializer.
var collectionView = UICollectionView(frame: yourFrame, collectionViewLayout: customCollectionViewLayout) // pass your custom collection view instance
thanks for replying . how can i use the initializer in the right way ? that is what i want . i know the way to connect it in story board but i can't connect it in code in the main class if that possible . i don't use story board
– Ahmed Seddek
Aug 23 at 15:57
@AhmedSeddek if you don't use storyboard, why is your
collectionView
an optional?– Rakesha Shastri
Aug 23 at 16:00
collectionView
i don't know , when i create it , xcode put optional front of it after adding delegate or data source or register the cell . am trying new animation through custom layout and i found the custom layout class in tutorial but it uses the same way u said by connecting it through story board not code :/
– Ahmed Seddek
Aug 23 at 16:11
@AhmedSeddek please show the code (edit it to the question) where you initialize the UICollectionView.
– Rakesha Shastri
Aug 23 at 16:12
this is the full code of my code and this is my TestCell class import UIKit class TestCell: BaseCell override func setupUI() backgroundColor = .purple
– Ahmed Seddek
Aug 23 at 16:14
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Hello and welcome to Stackoverflow. Could you kindly post your code as text rather than an image so it is easier to read.
– Chris Edgington
Aug 23 at 15:23