我目前正在尝试使用 UICollectionView 实现 UITableView 重新排序行为。
让我们调用一个UItableView TV和一个UICollectionView CV(澄清以下解释)
我基本上是在尝试重现电视的拖放,但我没有使用编辑模式,只要触发长按手势,单元格就可以移动。它工作得很好,我正在使用 CV 的移动方法,一切都很好。
我更新了 CV 的 contentOffset 属性以在用户拖动单元格时处理滚动。当用户转到顶部和底部的特定矩形时,我会更新 contentOffset 和 CV 滚动。问题是当用户停止移动手指时,手势不会发送任何更新,这会使滚动停止并在用户移动手指后立即重新开始。
这种行为绝对不自然,我宁愿继续滚动,直到用户释放 CV,就像电视中的情况一样。电视拖放体验很棒,我真的很想重现同样的感觉。有谁知道他们在重新排序期间如何管理电视中的滚动?
- 我尝试使用计时器重复触发滚动动作,只要手势位置在正确的位置,滚动很糟糕而且效率不高(非常缓慢和跳跃)。
- 我还尝试使用 GCD 在另一个线程中收听手势位置,但结果更糟。
我对此一无所知,所以如果有人有答案,我会嫁给他!
下面是 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];
}