I have a custom collection view layout which seems to produce some bugs. Or maybe I'm missing something. Layout looks like this and it's from here:
My problem is I can't pass the indexPath of the centered cell to pink button, call of centerCellIndexPath
produces nil. I also tried to preselect the cell in the layout itself, like so:
override open func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
// item's setup ......
// ...................
let finalPoint = CGPoint(x: newOffsetX, y: proposedContentOffset.y)
// Select cell in collectionView by Default
let updatePoint = CGPoint(x: newOffsetX, y: 180)
let indexPath = collectionView!.indexPathForItem(at: updatePoint)
self.collectionView!.selectItem(at: indexPath, animated: false, scrollPosition: [])
return finalPoint
}
But it doesn't work. I have to manually select the cell by swiping up, which is pretty unclear for user. How should I select the cell without tapping and swiping?
Any advice will be appreciated
UPD: After a night without a sleep finally managed it thanks to Vollan
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let position = 2 * scrollView.contentOffset.x / collectionView.superview!.frame.width
selectedItem = Int(round(position))
}
UPD: But the best just got better. Converted answer from linked to Swift version
This would be better code because it's cleaner and easier to read, all the content offset calculation is superfluous:
NSIndexPath *centerCellIndexPath =
[self.collectionView indexPathForItemAtPoint:
[self.view convertPoint:[self.view center] toView:self.collectionView]];
This would also be the correct representation of what you're actually trying to do: 1. Taking the center point of your viewcontroller's view - aka visual center point 2. convert it to the coordinate space of the view you're interested in - which is the collection view 3. Get the indexpath that exist at the location given.
So it takes 2 lines:
let centerPoint = self.view.convert(view.center, to: collectionView)
let indexPath = collectionView.indexPathForItem(at: centerPoint)
-> save media[indexPath.row]
And that was basically what Sachin Kishore suggested, but I didn't understand him at first
I kind of like the idea with dynamic indexPath but it takes some rounding, which is not reliable. So I think convert
and indexPathForItem
is the best here
If you were to put the logic into the scrollViewDidScroll
you can update an indexPath
dynamically.
let position = scrollView.contentOffset.x/(cellSize+spacing)
currenIndexPath.item = position
This should give you the current cells indexPath at all times.