I'm trying to create a UICollectionView with paging and that each item max width is 250 points, I've managed to create it, but I have 2 problems: The first item start not as it should be, but with more space at start and when I try to swipe, there is always something that wont let me swipe smooth.
This is how it looks:
video link
This is my code:
CenterCellCollectionFlowLayout.swift
class CenterCellCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
var attributesToReturn:[UICollectionViewLayoutAttributes] = super.layoutAttributesForElementsInRect(rect) as! [UICollectionViewLayoutAttributes]
for var i = 0 ; i < attributesToReturn.count ; i++
{
var currentLayoutAttributes: UICollectionViewLayoutAttributes = attributesToReturn[i]
var maximumSpacing: CGFloat = 50
let origin: CGFloat
if i - 1 >= 0 {
let previousLayoutAttributes = attributesToReturn[i - 1]
origin = previousLayoutAttributes.frame.maxX
} else {
origin = 0
}
if origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize().width
{
var frame: CGRect = currentLayoutAttributes.frame
frame.origin.x = origin + maximumSpacing
currentLayoutAttributes.frame = frame
}
}
return attributesToReturn
}
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5;
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth;
if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as? [UICollectionViewLayoutAttributes] {
var candidateAttributes : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.Cell {
continue
}
if let candAttrs = candidateAttributes {
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttrs.center.x - proposedContentOffsetCenterX
if fabsf(Float(a)) < fabsf(Float(b)) {
candidateAttributes = attributes;
}
}
else { // == First time in the loop == //
candidateAttributes = attributes;
continue;
}
}
return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y);
}
}
// Fallback
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
}
MainViewController.swift
class MainViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionViewFlowLayout: CenterCellCollectionViewFlowLayout!
var collectionObjects: NSMutableArray?
private let reuseIdentifier = "CollectionViewCell"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell
cell.backgroundColor = UIColor.greenColor()
// Configure the cell
return cell
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
{
return UIEdgeInsetsMake(0, 0, 0, 0)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
return CGSizeMake(250, 250)
}
}
Thanks in advance
An object that manages an ordered collection of data items and presents them using customizable layouts.
You need to reduce the height of UICollectionView to its cell / item height and select " Horizontal " from the " Scroll Direction " as seen in the screenshot below. Then it will scroll horizontally depending on the numberOfItems you have returned in its datasource implementation.
UICollectionView makes adding custom layouts and layout transitions, like those in Photos, simple to build. You're not limited to stacks and grids because collection views are customizable. You can use them to make circle layouts, cover-flow style layouts, Pulse news style layouts and almost anything you can dream up!
A UICollectionView inherits from UIScrollView. It is possible to achieve paging by setting isPagingEnabled to true.
So I figure out how to do it.
First create a custom UICollectionViewFlowLayout and add this override this method:
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
if let cv = self.collectionView {
let cvBounds = cv.bounds
let halfWidth = cvBounds.size.width * 0.5;
let proposedContentOffsetCenterX = proposedContentOffset.x + halfWidth;
if let attributesForVisibleCells = self.layoutAttributesForElementsInRect(cvBounds) as? [UICollectionViewLayoutAttributes] {
var candidateAttributes : UICollectionViewLayoutAttributes?
for attributes in attributesForVisibleCells {
// == Skip comparison with non-cell items (headers and footers) == //
if attributes.representedElementCategory != UICollectionElementCategory.Cell {
continue
}
if let candAttrs = candidateAttributes {
let a = attributes.center.x - proposedContentOffsetCenterX
let b = candAttrs.center.x - proposedContentOffsetCenterX
if fabsf(Float(a)) < fabsf(Float(b)) {
candidateAttributes = attributes;
}
}
else { // == First time in the loop == //
candidateAttributes = attributes;
continue;
}
}
return CGPoint(x : candidateAttributes!.center.x - halfWidth, y : proposedContentOffset.y);
}
}
// Fallback
return super.targetContentOffsetForProposedContentOffset(proposedContentOffset)
}
Then on the class that you implement the UICollectionView do like that:
let collectionViewLayout: CenterCellCollectionViewFlowLayout = CenterCellCollectionViewFlowLayout()
collectionViewLayout.itemSize = CGSizeMake(self.itemSize, self.itemSize)
collectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
collectionViewLayout.minimumInteritemSpacing = 0
collectionViewLayout.minimumLineSpacing = self.itemSpacing
collectionViewLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
var collectionView: UICollectionView = UICollectionView(frame: self.collectionContainer.bounds, collectionViewLayout: collectionViewLayout)
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.backgroundColor = UIColor.redColor()
collectionView.registerClass(LevelsCustomCell.self, forCellWithReuseIdentifier: reuseIdentifier)
collectionView.registerNib(UINib(nibName: reuseIdentifier, bundle: nil), forCellWithReuseIdentifier: reuseIdentifier)
self.collectionContainer.addSubview(collectionView)
Thats about it, works like a charm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With