Domanda

Attualmente sto cercando di implementare il comportamento di riordinamento dell'UniutibleView utilizzando UicollectionView.

Chiamiamo un UilableView TV e un UicollectionVisualizza CV (per chiarire la seguente spiegazione)

Sto fondamentalmente cercando di riprodurre la resistenza e la goccia della TV, ma non sto usando la modalità di modifica, la cella è pronta per essere spostata non appena viene attivato il gesto della pressione lungo. Funziona perfettamente, sto usando il metodo di spostamento del CV, tutto va bene.

Aggiornare la proprietà ContentoFset del CV per gestire lo scorrimento quando l'utente trascina una cella. Quando un utente va su un particolare retto in alto e in basso, aggiorno ContentoFSet e il rotolo CV. Il problema è quando l'utente smette di spostarlo il dito, il gesto non invia alcun aggiornamento che rende il rotolo di scorrimento e ricominciare non appena l'utente sposta il dito.

Questo comportamento non è assolutamente naturale, preferirei continuare di scorrere fino a quando l'utente rilascia il CV come è il caso in TV. L'esperienza Tv Drag & Drop è fantastica e voglio davvero riprodurre la stessa sensazione. Qualcuno sa come gestiscono il rotolo in TV durante il riordino?

    .
  • Ho provato a usare un timer per attivare ripetutamente un'azione di scorrimento finché la posizione del gesto è nel punto giusto, il rotolo è stato orribile e non molto produttivo (molto lento e nervoso).
  • Ho anche provato a usare GCD per ascoltare la posizione del gesto in un altro thread, ma il risultato è anche peggiore.

Ho finito l'idea di questo, quindi se qualcuno ha la risposta, lo sposerei!

Ecco l'implementazione del metodo 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];}];
    }
}
.

Per fare il rotolo CV, sto usando quel metodo:

- (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];
}
.

È stato utile?

Soluzione

Questo potrebbe aiutare

https://github.com/lxcid/lxreorderAbleCollectionViewFlowReordre

Si estende il UICollectionView per consentire a ciascun generacolodicetagcode di essere riorganizzato manualmente dall'utente con un tocco lungo (aka touch-and-hold).L'utente può trascinare la cella in qualsiasi altra posizione nella raccolta e le altre celle si riordinano automaticamente.Grazie Vai a lxcid per questo.

Altri suggerimenti

qui è un'alternativa:

Le differenze tra DragGableCollectionView e lxreOdeorderAbleCollectionViewFlowlayout sono:

    .
  • L'origine dati è cambiata solo una volta. Ciò significa che mentre l'utente trascinando un elemento le celle vengono riposizionate senza modificare l'origine dati.
  • È scritto in modo tale da utilizzare con layout personalizzati.
  • Utilizza un CADisplayLink per lo scorrimento e l'animazione liscia.
  • Le animazioni vengono annullate meno frequentemente durante il trascinamento. Si sente più "naturale".
  • Il protocollo estende UICollectionViewDataSource con metodi simili a UITableViewDataSource.

È un lavoro in corso. Le sezioni multiple sono ora supportate.

Per usarlo con un layout personalizzato, vedere DraggableCollectionViewFlowLayout. La maggior parte della logica esiste in LSCollectionViewLayoutHelper. C'è anche un esempio in Circlelayoutdemo che mostra come rendere l'esempio circlelayout di Apple da WWDC 2012 il lavoro.

A partire da iOS 9, UICollectionView ora supporta il riordino.

Per UICollectionViewControllers, basta ignorare collectionView(collectionView: UICollectionView, moveItemAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)

Per UICollectionViews, dovrai gestire i gesti da te stesso oltre ad implementare il metodo UICollectionViewDataSource sopra.

Ecco il codice dalla fonte:

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()
    }
}
.

Fonti: https://Developer.apple.com/library/ios/documentation/uikit/reference/uicollectionview_class/#//apple_ref/doc/uid/tp40012177-ch1-sw67

http://nshint.io/blog/ 2015/07/16 / UicollectionViews-Now-have-Easy-riordinging /

Se vuoi sperimentare rotolare il tuo, ho appena scritto un tutorial in Swift basato su cui puoi guardare.Ho provato a costruire il più basico dei casi in modo da essere più facile da seguire questo .

qui è un altro approccio:

La differenza chiave è che questa soluzione non richiede una cella "fantasma" o "dummy" per fornire la funzionalità di trascinamento del trascinamento.Usa semplicemente la cella stessa.Le animazioni sono in linea con l'inteableview.Funziona regolando il dataSource privato del layout della vista della collezione mentre si muove.Una volta che hai lasciato andare, dirà il tuo controller che puoi commettere la modifica al tuo DataSource.

Credo che sia un po 'più semplice da lavorare per la maggior parte dei casi di utilizzo.Ancora un lavoro in corso, ma ancora un altro modo per realizzarlo.La maggior parte dovrebbe trovare questo abbastanza facile da incorporare nei propri personalizzati UicollectionViewLayouts.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top