'Collection view auto-scrolling on gesture based rearrangement
I have an app where photos gets listed in the collection view in multiple sections, got the feature request to add the rearrangement so I added the gesture based rearrangement to collection view.
Issue: after a bit of rearrangement, it got to a stage where the collection view automatically got scrolled to the bottom of the screen. If I try to scroll back up, it got scrolled back automatically to bottom of the screen.
Any help would be greatly appreciated.
Stack trace
#0 0x00000001274dc952 in -[UIScrollView setContentOffset:] ()
#1 0x0000000126614327 in -[UICollectionView setContentOffset:] ()
#2 0x00000001274ff1d3 in -[UIScrollView _setContentOffset:animated:animationCurve:animationAdjustsForContentOffsetDelta:animation:animationConfigurator:] ()
#3 0x00000001274fee62 in -[UIScrollView _setContentOffset:animated:animationCurve:animationAdjustsForContentOffsetDelta:animation:] ()
#4 0x000000012661429f in -[UICollectionView setContentOffset:animated:] ()
#5 0x0000000126634c2c in -[UICollectionView _autoScrollAssistantUpdateContentOffset:] ()
#6 0x00000001273eebd1 in -[_UIAutoScrollAssistant _handleAutoScrollerWithContentOffset:direction:] ()
#7 0x00000001273eeb0c in -[_UIAutoScrollAssistant displayLinkFired:] ()
#8 0x0000000113d250ec in CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) ()
#9 0x0000000113e1d435 in display_timer_callback(__CFMachPort*, void*, long, void*) ()
#10 0x000000011520075d in __CFMachPortPerform ()
#11 0x00000001152346e1 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ ()
#12 0x0000000115233aae in __CFRunLoopDoSource1 ()
#13 0x000000011522dfe8 in __CFRunLoopRun ()
#14 0x000000011522d0f3 in CFRunLoopRunSpecific ()
#15 0x000000011aee3cd3 in GSEventRunModal ()
#16 0x0000000126fb4f42 in -[UIApplication _run] ()
#17 0x0000000126fb9b5e in UIApplicationMain ()
Here is the code
CollectionView
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.bounces = false
collectionView.backgroundColor = .white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(CustomCell.self, forCellWithReuseIdentifier: reuseIden)
collectionView.contentInset = .init(top: 18, left: 0, bottom: 18, right: 0)
return collectionView
}()
Gesture recognizer
private func addGestureRecognizer() {
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongGesture(gesture:)))
longPressGesture.minimumPressDuration = 0.5
longPressGesture.allowableMovement = 1
collectionView.addGestureRecognizer(longPressGesture)
}
@objc func handleLongGesture(gesture: UILongPressGestureRecognizer) {
switch(gesture.state) {
case .began:
guard let selectedIndexPath = collectionView.indexPathForItem(at: gesture.location(in: collectionView)) else {
break
}
collectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
case .changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.location(in: collectionView))
case .ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}
Move item
extension CollectionViewController {
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
return true
}
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
collectionView.performBatchUpdates({
let row = sections[sourceIndexPath.section].rows.remove(at: sourceIndexPath.item)
sections[destinationIndexPath.section].rows.insert(row, at: destinationIndexPath.item)
}, completion: { _ in
DispatchQueue.main.async {
self.collectionView.reloadData()
}
})
}
func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath {
return proposedIndexPath
}
}
Data source and delegates
extension CollectionViewController:
UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int { sections[section].rows.count }
func numberOfSections(in collectionView: UICollectionView) -> Int { sections.count }
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIden, for: indexPath) as! CustomCell
return cell
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat { StandardPadding }
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { StandardPadding }
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionWidth = collectionView.frame.width
let itemWidth = (collectionWidth/2)-StandardPadding*1.5
return .init(width: itemWidth, height: (itemWidth*IMAGERATIO))
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .init(top: StandardPadding, left: StandardPadding, bottom: StandardPadding, right: StandardPadding)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

