現在、UICollectionViewを使用してUITableViewの並べ替え動作を実装しようとしています。
ItableView TVとICollectionView CVを呼び出しましょう(以下の説明を明確にするため)
私は基本的にテレビのドラッグ&ドロップを再現しようとしていますが、編集モードを使用していません。長押しジェスチャーがトリガーされるとすぐにセルを移動する準備ができています。それは完璧に動作します、私はCVの移動方法を使用しています、すべてがうまくいきます。
CVのcontentOffsetプロパティを更新して、ユーザーがセルをドラッグしているときにスクロールを処理します。ユーザーが上下の特定の四角形に移動すると、contentOffsetとCVスクロールを更新します。問題は、ユーザーが指の動きを止めると、ジェスチャーが更新を送信しないため、ユーザーが指を動かすとすぐにスクロールが停止して再開することです。
この動作は間違いなく自然なことではありません。テレビの場合のように、ユーザーがCVを放すまでスクロールし続けることをお勧めします。 TVのドラッグアンドドロップ操作はすばらしく、同じ感覚を再現したいです。再注文中にテレビのスクロールを管理する方法を知っている人はいますか?
私はそれについての考えを使い果たしたので、誰かが答えを持っているなら、私は彼と結婚するでしょう!
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];
}
これは役立つかもしれません
https://github.com/lxcid/LXReorderableCollectionViewFlowLayout
これにより、UICollectionView
が拡張され、UICollectionViewCells
のそれぞれを、ユーザーが長いタッチ(別名、タッチアンドホールド)で手動で再配置できるようになります。ユーザーはセルをコレクション内の他の位置にドラッグでき、他のセルは自動的に並べ替えられます。 lxcid に感謝します。
ここ は代替です:
DraggableCollectionViewと LXReorderableCollectionViewFlowLayout の違いは次のとおりです。
CADisplayLink
を使用して、スムーズなスクロールとアニメーションを実現します。UICollectionViewDataSource
と同様のメソッドでUITableViewDataSource
を拡張します。それは進行中の作業です。複数のセクションがサポートされるようになりました。
カスタムレイアウトで使用するには、DraggableCollectionViewFlowLayout
を参照してください。ほとんどのロジックはLSCollectionViewLayoutHelper
に存在します。 CircleLayoutDemoには、WWDC 2012のAppleのCircleLayoutの例を機能させる方法を示す例もあります。
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-now-have-easy-reordering/
独自のロールアウトを実験したい場合は、Swiftに基づいたチュートリアルを作成しました。簡単に理解できるように、最も基本的なケースを作成しようとしました this 。
ここ は別のアプローチです:
主な違いは、このソリューションでは、ドラッグアンドドロップ機能を提供するために「ゴースト」または「ダミー」セルが必要ないことです。単にセル自体を使用します。アニメーションはUITableViewに沿っています。コレクションビューレイアウトのプライベートデータソースを調整しながら動作します。放すと、コントローラーに変更を自分のデータソースにコミットできることを伝えます。
ほとんどのユースケースで作業する方が少し簡単だと思います。まだ進行中の作業ですが、これを達成するためのさらに別の方法です。ほとんどの場合、これを独自のカスタムUICollectionViewLayoutsに組み込むのは非常に簡単です。