Concetti fondamentali

Le seguenti sezioni spiegano alcuni concetti chiave della procedura di trascinamento.

Procedura di trascinamento

La procedura di trascinamento prevede quattro passaggi o stati: avviato, continuo, eliminato e terminato.

Avviato

In risposta al gesto di trascinamento di un utente, l'applicazione chiama startDragAndDrop() per indicare al sistema di avviare un'operazione di trascinamento. Gli argomenti del metodo offrono quanto segue:

  • I dati da trascinare.
  • Un callback per disegnare l'ombra trascinata
  • Metadati che descrivono i dati trascinati
  • Il sistema risponde richiamando l'applicazione per ottenere un'ombra a trascinamento. Il sistema visualizza l'ombra trascinata sul dispositivo.
  • Successivamente, il sistema invia un evento di trascinamento con tipo di azione ACTION_DRAG_STARTED all'ascoltatore di eventi di trascinamento di tutti i View oggetti nel layout corrente. Per continuare a ricevere eventi di trascinamento, incluso un possibile evento di trascinamento, il listener di eventi di trascinamento deve restituire true. Questo registra il listener nel sistema. Solo i listener registrati continuano a ricevere eventi di trascinamento. A questo punto, i listener possono anche modificare l'aspetto dell'oggetto View della destinazione di rilascio per indicare che la visualizzazione può accettare un evento di rilascio.
  • Se il listener di eventi di trascinamento restituisce false, non riceve eventi di trascinamento per l'operazione corrente finché il sistema non invia un evento di trascinamento con il tipo di azione ACTION_DRAG_ENDED. Se restituisci false, il listener comunica al sistema che non è interessato all'operazione di trascinamento e non vuole accettare i dati trascinati.
Avanzamento
L'utente continua a trascinare. Quando l'ombra di trascinamento interseca il riquadro di selezione di una destinazione, il sistema invia uno o più eventi di trascinamento al listener di eventi di trascinamento della destinazione. Il listener potrebbe modificare l'aspetto della destinazione di rilascio View in risposta all'evento. Ad esempio, se l'evento indica che l'ombra di trascinamento entra nel riquadro di delimitazione della destinazione del rilascio (tipo di azione ACTION_DRAG_ENTERED), il listener può reagire evidenziando View.
Interrotto
L'utente rilascia l'ombra di trascinamento all'interno del riquadro di delimitazione di una destinazione. Il sistema invia al listener della destinazione di rilascio un evento di trascinamento con il tipo di azione ACTION_DROP. L'oggetto evento di trascinamento contiene i dati passati al sistema nella chiamata a startDragAndDrop() che avvia l'operazione. Se il listener elabora correttamente i dati eliminati dovrebbe restituire il valore booleano true nel sistema. : questo passaggio si verifica solo se l'utente rilascia l'ombra di trascinamento all'interno del riquadro di delimitazione di un View il cui listener è registrato per ricevere eventi di trascinamento (una destinazione di rilascio). Se l'utente rilascia l'ombra di trascinamento in qualsiasi altra situazione, non viene inviato alcun evento di trascinamento ACTION_DROP.
Terminato

Dopo che l'utente ha rilasciato l'ombra trascinata e dopo che il sistema ha inviato

un evento di trascinamento con tipo di azione ACTION_DROP. Se necessario, il sistema invia un evento di trascinamento con il tipo di azione ACTION_DRAG_ENDED per indicare che l'operazione di trascinamento è terminata. Ciò avviene indipendentemente da dove l'utente rilascia l'ombra di trascinamento. L'evento viene inviato a ogni listener registrato per ricevere eventi di trascinamento, anche se il listener riceve anche l'evento ACTION_DROP.

Ciascuno di questi passaggi è descritto più dettagliatamente nella sezione Un'operazione di trascinamento.

Eventi di trascinamento

Il sistema invia un evento di trascinamento sotto forma di oggetto DragEvent, che contiene un tipo di azione che descrive cosa sta succedendo nel processo di trascinamento. A seconda del tipo di azione, l'oggetto può contenere anche altri dati.

I listener di eventi di trascinamento ricevono l'oggetto DragEvent. Per ottenere il tipo di azione, gli ascoltatori chiamano DragEvent.getAction(). Esistono sei possibili valori definiti da costanti nella classe DragEvent, descritti nella tabella 1:

Tabella 1. Tipi di azioni DragEvent

Tipo di azione Significato
ACTION_DRAG_STARTED L'applicazione chiama startDragAndDrop() e ottiene un'ombra di trascinamento. Se il listener vuole continuare a ricevere eventi di trascinamento per questa operazione, deve restituire il valore booleano true al sistema.
ACTION_DRAG_ENTERED L'ombra di trascinamento entra nel riquadro di delimitazione del listener di eventi di trascinamento View. Questo è il primo tipo di azione di evento che il listener riceve quando l'ombra di trascinamento entra nel riquadro di delimitazione.
ACTION_DRAG_LOCATION Dopo un evento ACTION_DRAG_ENTERED, l'ombra di trascinamento si trova ancora all'interno del riquadro di delimitazione dell'View del listener di eventi di trascinamento.
ACTION_DRAG_EXITED Dopo un ACTION_DRAG_ENTERED e almeno un ACTION_DRAG_LOCATION evento, l'ombra di trascinamento si sposta fuori dal riquadro di selezione del listener View del listener di eventi di trascinamento.
ACTION_DROP L'ombra di trascinamento viene rilasciata sul valore View del listener di eventi di trascinamento. Questo tipo di azione viene inviato al listener di un oggetto View solo se il listener restituisce il valore booleano true in risposta all'evento di trascinamento ACTION_DRAG_STARTED. Questo tipo di azione non viene inviato se l'utente rilascia l'ombra di trascinamento su un View il cui listener non è registrato o se l'utente rilascia l'ombra di trascinamento su qualsiasi elemento che non fa parte del layout corrente.

Il listener restituisce l'elemento booleano true se elabora correttamente il calo. In caso contrario, deve restituire false.

ACTION_DRAG_ENDED Il sistema sta terminando l'operazione di trascinamento. Questo tipo di azione non è necessariamente preceduto da un evento ACTION_DROP. Se il sistema invia un messaggio ACTION_DROP, la ricezione del tipo di azione ACTION_DRAG_ENDED non implica che il rilascio sia riuscito. Il listener deve chiamare getResult(), come mostrato nella tabella 2, per ottenere il valore restituito in risposta a ACTION_DROP. Se un evento ACTION_DROP non viene inviato, getResult() restituisce false.

L'oggetto DragEvent contiene anche i dati e i metadati che l'applicazione fornisce al sistema nella chiamata a startDragAndDrop(). Alcuni dati sono validi solo per determinati tipi di azioni, come riepilogato nella tabella 2. Per ulteriori informazioni sugli eventi e sui relativi dati, consulta la sezione Un'operazione di trascinamento.

Tabella 2. Dati DragEvent validi per tipo di azione

getAction()
valore
getClipDescription()
valore
getLocalState()
valore
getX()
valore
getY()
valore
getClipData()
valore
getResult()
valore
ACTION_DRAG_STARTED ✓ ✓        
ACTION_DRAG_ENTERED ✓ ✓        
ACTION_DRAG_LOCATION ✓ ✓ ✓ ✓    
ACTION_DRAG_EXITED ✓ ✓        
ACTION_DROP ✓ ✓ ✓ ✓ ✓  
ACTION_DRAG_ENDED   ✓       ✓

I metodi DragEvent getAction(), describeContents(), writeToParcel() e toString() restituiscono sempre dati validi.

Se un metodo non contiene dati validi per un determinato tipo di azione, restituisce null o 0, a seconda del tipo di risultato.

Trascina ombra

Durante un'operazione di trascinamento, il sistema visualizza un'immagine che l'utente trascina. Per lo spostamento dei dati, questa immagine rappresenta i dati trascinati. Per altre operazioni, l'immagine rappresenta alcuni aspetti dell'operazione di trascinamento.

L'immagine è chiamata ombra di trascinamento. Puoi crearlo con i metodi dichiarati per un oggetto View.DragShadowBuilder. Il builder al sistema quando avvii un'operazione di trascinamento utilizzando startDragAndDrop(). Come parte della risposta a startDragAndDrop(), il sistema richiama i metodi di callback che hai definito in View.DragShadowBuilder per ottenere un'ombreggiatura a trascinamento.

La classe View.DragShadowBuilder ha due costruttori:

View.DragShadowBuilder(View)

Questo costruttore accetta tutti gli oggetti View dell'applicazione. Il costruttore archivia l'oggetto View nell'oggetto View.DragShadowBuilder, in modo che i callback possano accedervi per creare l'ombra di trascinamento. La vista non deve essere necessariamente un View selezionato dall'utente per avviare l'operazione di trascinamento.

Se utilizzi questo costruttore, non è necessario estendere View.DragShadowBuilder o sovrascrivere i relativi metodi. Per impostazione predefinita, viene visualizzata un'ombra a trascinamento che ha lo stesso aspetto del View trasmesso come argomento, centrato nella posizione in cui l'utente tocca lo schermo.

View.DragShadowBuilder()

Se utilizzi questo costruttore, nell'oggetto View.DragShadowBuilder non sarà disponibile nessun oggetto View. Il campo è impostato su null. Devi estendere View.DragShadowBuilder e sovrascrivere i relativi metodi, altrimenti otterrai un'ombreggiatura invisibile di trascinamento. Il sistema non genera un errore.

La classe View.DragShadowBuilder ha due metodi che insieme creano l'ombra di trascinamento:

onProvideShadowMetrics()

Il sistema chiama questo metodo subito dopo la chiamata a startDragAndDrop(). Utilizza il metodo per inviare le dimensioni e il punto di contatto dell'ombra di trascinamento al sistema. Il metodo ha due parametri:

outShadowSize: un oggetto Point. La larghezza dell'ombra di trascinamento va in x e l'altezza deve essere in y.

outShadowTouchPoint: un oggetto Point. Il punto di contatto è la posizione all'interno dell'ombra del trascinamento che deve trovarsi sotto il dito dell'utente durante il trascinamento. La sua posizione X va in x e la sua posizione Y va in y.

onDrawShadow()

Subito dopo la chiamata a onProvideShadowMetrics(), il sistema chiama onDrawShadow() per creare l'ombra di trascinamento. Il metodo ha un singolo argomento, un oggetto Canvas che il sistema crea dai parametri che fornisci in onProvideShadowMetrics(). Il metodo disegna l'ombra di trascinamento sull'elemento Canvas fornito.

Per migliorare le prestazioni, riduci le dimensioni dell'ombra di trascinamento. Per un singolo elemento, è consigliabile utilizzare un'icona. Per una selezione di più elementi, potresti voler utilizzare icone in pila anziché immagini complete sparse sullo schermo.

Listener di eventi di trascinamento e metodi di callback

Un View riceve eventi di trascinamento con un listener di eventi di trascinamento che implementa View.OnDragListener o con il metodo di callback onDragEvent() della vista. Quando il sistema chiama il metodo o il listener, fornisce un argomento DragEvent.

Nella maggior parte dei casi, è preferibile utilizzare un listener che utilizzare il metodo di callback. Quando progetti UI, di solito non sottoclassi le classi View, ma se usi il metodo di callback, devi creare delle sottoclassi per sostituire il metodo. A confronto, puoi implementare una classe listener e quindi utilizzarla con più oggetti View diversi. Puoi implementarla anche come classe in linea anonima o espressione lambda. Per impostare il listener per un oggetto View, chiama setOnDragListener().

In alternativa, puoi modificare l'implementazione predefinita di onDragEvent() senza eseguire l'override del metodo. Impostare un elemento OnReceiveContentListener su una vista. Per ulteriori dettagli, consulta setOnReceiveContentListener(). Per impostazione predefinita, il metodo onDragEvent() effettua le seguenti operazioni:

  • Restituisce true in risposta alla chiamata a startDragAndDrop().
  • Chiamate performReceiveContent() se i dati relativi al trascinamento vengono rilasciati nella vista. I dati vengono passati al metodo come oggetto ContentInfo. Il metodo richiama OnReceiveContentListener.

  • Restituisce true se i dati di trascinamento vengono eliminati nella vista e OnReceiveContentListener consuma qualsiasi contenuto.

Definisci il OnReceiveContentListener per gestire i dati specificamente per la tua app. Per la compatibilità con le versioni precedenti al livello API 24, utilizza la versione Jetpack di OnReceiveContentListener.

Per un oggetto View puoi avere un listener di eventi di trascinamento e un metodo di callback, nel qual caso il sistema chiama prima il listener. Il sistema non chiama il metodo di callback, a meno che il listener non restituisca false.

La combinazione del metodo onDragEvent() e di View.OnDragListener è analoga alla combinazione di onTouchEvent() e View.OnTouchListener utilizzati con gli eventi tocco.