UICollectionViewの有効なドラッグアンドドロップ
-
13-12-2019 - |
質問
現在、UICollectionViewを使用してUITableView並べ替え動作を実装しようとしています。
uicativeview tv と uicollectionview cv を呼んでみましょう(以下の説明を明確にするため)
基本的にテレビのドラッグ&ドロップを再現しようとしていますが、編集モードを使用していないため、長押しジェスチャがトリガーされるとすぐにセルを移動する準備ができています。それは都道府県で働いています、私はCVの移動方法を使っています、すべてが大丈夫です。
ユーザーがセルをドラッグしているときにスクロールを処理するようにCVのContentOffsetプロパティを更新します。ユーザーが上部と下部にある特定の四角に移動すると、ContentOffsetとCVスクロールを更新します。問題は、ユーザーが指の動きを止めるとき、ジェスチャーはスクロールを停止させ、ユーザーが自分の指を移動するとすぐに再び開始する更新を送信しません。
この動作は間違いなく自然ではないが、私はそれがテレビでの場合としてCVを解放するまでスクロールするように連続することを好むでしょう。 TVドラッグ&ドロップの経験は素晴らしいです、そして私は本当に同じ気持ちを再現したいです。誰もが並べ替え中にテレビのスクロールを管理する方法を知っていますか?
- ジェスチャーの位置が正しい場所にある限り、スクロール動作を繰り返しトリガーするためにタイマーを使って、スクロールはひどく、あまり生産的ではありません(非常に遅くてびっくり)。
- 私はまたGCDを使って別のスレッドでジェスチャ位置を聞いてみましたが、結果はさらに最悪です。
私はそれについて考えを使い果たしたので、誰かが私が彼と結婚するだろう!
これは長押し方法の実装です:
- (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];
}
. 他のヒント
ここは代替案:
DragGableCollectionViewと
iOS 9以降、UICollectionView
は並べ替えをサポートしています。
UICollectionViewController
sの場合は、collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
UICollectionView
sの場合、上記の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-easy-readering /
あなたがあなた自身を転がしてみると、あなたが見ることができる迅速なチュートリアルを書いたばかりです。この。
ここは別のアプローチです:
鍵の違いは、この解決策が「ゴースト」または「ダミー」セルを必要としないため、ドラッグアンドドロップ機能を提供します。それは単にセル自体を使います。アニメーションはuibiteviewと並んでいます。移動中にコレクションビューレイアウトのプライベートデータソースを調整することで機能します。手放すと、自分のデータソースに変更をコミットできるようにコントローラに伝えます。
ほとんどのユースケースでは働くのは少し簡単だと思います。それでも進行中の仕事ですが、これを達成するもう1つの方法です。ほとんどの場合、これは彼ら自身のカスタムUICollectionViewLayoutsに組み込むことが非常に簡単です。