我目前正在尝试使用UICollectionView实现UITableView重新排序行为。
让我们调用 UItableView TV 和 UICollectionView CV (以澄清以下说明)
我基本上试图重现电视的拖放,但我没有使用编辑模式,一旦触发了长按手势,单元就可以移动了。它完美地工作,我使用简历的移动方法,一切都很好。
我更新CV的contentOffset属性以在用户拖动单元格时处理滚动。当用户转到顶部和底部的特定矩形时,我更新了contentOffset和CV滚动。问题是当用户停止移动手指时,手势不会发送任何更新,这会使滚动停止并在用户移动手指后立即重新开始。
这种行为绝对不自然,我宁愿继续滚动,直到用户发布CV,就像在电视中一样。电视拖放体验真棒,我真的想重现同样的感觉。有没有人知道他们在重新排序时如何管理电视中的滚动?
我对此没有任何想法,所以如果有人有答案,我会嫁给他!
以下是longPress方法的实现:
- (void)handleLongPress:(UILongPressGestureRecognizer *)sender
{
ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGPoint gesturePosition = [sender locationInView:self.collectionView];
NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:gesturePosition];
if (sender.state == UIGestureRecognizerStateBegan)
{
layout.selectedItem = selectedIndexPath;
layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
}
else if (sender.state == UIGestureRecognizerStateChanged)
{
layout.gesturePoint = gesturePosition; // Setting gesturePoint invalidate layout
[self swapCellAtPoint:gesturePosition];
[self manageScrollWithReferencePoint:gesturePosition];
}
else
{
[self.collectionView performBatchUpdates:^
{
layout.selectedItem = nil;
layout.gesturePoint = CGPointZero; // Setting gesturePoint invalidate layout
} completion:^(BOOL completion){[self.collectionView reloadData];}];
}
}
要进行CV滚动,我正在使用该方法:
- (void)manageScrollWithReferencePoint:(CGPoint)gesturePoint
{
ReorganizableCVCLayout *layout = (ReorganizableCVCLayout *)self.collectionView.collectionViewLayout;
CGFloat topScrollLimit = self.collectionView.contentOffset.y+layout.itemSize.height/2+SCROLL_BORDER;
CGFloat bottomScrollLimit = self.collectionView.contentOffset.y+self.collectionView.frame.size.height-layout.itemSize.height/2-SCROLL_BORDER;
CGPoint contentOffset = self.collectionView.contentOffset;
if (gesturePoint.y < topScrollLimit && gesturePoint.y - layout.itemSize.height/2 - SCROLL_BORDER > 0)
contentOffset.y -= SCROLL_STEP;
else if (gesturePoint.y > bottomScrollLimit &&
gesturePoint.y + layout.itemSize.height/2 + SCROLL_BORDER < self.collectionView.contentSize.height)
contentOffset.y += SCROLL_STEP;
[self.collectionView setContentOffset:contentOffset];
}
答案 0 :(得分:70)
这可能会有所帮助
https://github.com/lxcid/LXReorderableCollectionViewFlowLayout
这扩展了UICollectionView
以允许用户通过长触摸(也称为触摸并保持)手动重新排列每个UICollectionViewCells
。用户可以将Cell拖动到集合中的任何其他位置,其他单元格将自动重新排序。谢谢你转到lxcid。
答案 1 :(得分:47)
Here是另一种选择:
DraggableCollectionView和LXReorderableCollectionViewFlowLayout之间的区别是:
CADisplayLink
进行平滑滚动和动画制作。UICollectionViewDataSource
类似的方法扩展UITableViewDataSource
。这是一项正在进行中的工作。现在支持多个部分。
要将其与自定义布局一起使用,请参阅DraggableCollectionViewFlowLayout
。大多数逻辑都存在于LSCollectionViewLayoutHelper
中。 CircleLayoutDemo中还有一个示例,展示了如何从WWDC 2012开始制作Apple的CircleLayout示例。
答案 2 :(得分:30)
从iOS 9开始,UICollectionView
现在支持重新排序。
对于UICollectionViewController
,只需覆盖collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
对于UICollectionView
,除了实施上述UICollectionViewDataSource
方法之外,您还必须自己处理手势。
这是源代码:
private var longPressGesture: UILongPressGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
longPressGesture = UILongPressGestureRecognizer(target: self, action: "handleLongGesture:")
self.collectionView.addGestureRecognizer(longPressGesture)
}
func handleLongGesture(gesture: UILongPressGestureRecognizer) {
switch(gesture.state) {
case UIGestureRecognizerState.Began:
guard let selectedIndexPath = self.collectionView.indexPathForItemAtPoint(gesture.locationInView(self.collectionView)) else {
break
}
collectionView.beginInteractiveMovementForItemAtIndexPath(selectedIndexPath)
case UIGestureRecognizerState.Changed:
collectionView.updateInteractiveMovementTargetPosition(gesture.locationInView(gesture.view!))
case UIGestureRecognizerState.Ended:
collectionView.endInteractiveMovement()
default:
collectionView.cancelInteractiveMovement()
}
}
http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/
答案 3 :(得分:3)
如果您想尝试自己推出,我只是写了一个基于Swift的教程,你可以看看。我尝试构建最基本的案例,以便更容易理解this。
答案 4 :(得分:2)
Here是另一种方法:
关键区别在于此解决方案不需要“ghost”或“dummy”单元来提供拖放功能。它只是使用细胞本身。动画符合UITableView。它的工作原理是在移动时调整集合视图布局的私有数据源。一旦放手,它将告诉您的控制器您可以将更改提交到您自己的数据源。
我认为在大多数用例中使用它会更简单一些。仍在进行中,但还有另一种方法可以实现这一目标。大多数人都应该发现这很容易合并到他们自己的自定义UICollectionViewLayouts中。