Concetti fondamentali

Prova Compose
Jetpack Compose è il toolkit UI consigliato per Android. Scopri come utilizzare il trascinamento in Compose.

Le sezioni seguenti illustrano alcuni concetti chiave per il processo di trascinamento.

Processo di trascinamento

Il processo di trascinamento prevede quattro passaggi o stati: avviato, in corso, rilasciato e terminato.

Avviata

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

  • I dati da trascinare.
  • Un callback per disegnare l'ombra di trascinamento
  • I metadati che descrivono i dati trascinati
  • Il sistema risponde richiamando l'applicazione per ottenere un'ombra di trascinamento. Il sistema visualizza quindi l'ombra di trascinamento sul dispositivo.
  • Successivamente, il sistema invia un evento di trascinamento con il tipo di azione ACTION_DRAG_STARTED al listener di eventi di trascinamento di tutti gli oggetti View nel layout corrente. Per continuare a ricevere eventi di trascinamento, incluso un possibile evento di rilascio, il listener di eventi di trascinamento deve restituire true. In questo modo, il listener viene registrato 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 mostrare 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. Restituendo false, il listener indica al sistema che non è interessato all'operazione di trascinamento e non vuole accettare i dati trascinati.
Operazione in corso…
L'utente continua a trascinare. Quando l'ombra di trascinamento interseca il riquadro di delimitazione di una destinazione di rilascio, il sistema invia uno o più eventi di trascinamento al listener di eventi di trascinamento della destinazione. Il listener potrebbe modificare l'aspetto della View della destinazione di rilascio in risposta all'evento. Ad esempio, se l'evento indica che l'ombra di trascinamento entra nel riquadro di delimitazione della destinazione di rilascio (tipo di azione ACTION_DRAG_ENTERED ), il listener può reagire evidenziando la View.
Rilasciato
L'utente rilascia l'ombra di trascinamento all'interno del riquadro di delimitazione di una destinazione di rilascio. Il sistema invia al listener della destinazione di rilascio un evento di trascinamento con action type ACTION_DROP. L'oggetto evento di trascinamento contiene i dati che vengono passati al sistema nella chiamata a startDragAndDrop() che avvia l'operazione. Il listener deve restituire il valore booleano true al sistema se elabora correttamente i dati rilasciati. : questo passaggio si verifica solo se l'utente rilascia l'ombra di trascinamento all'interno del riquadro di delimitazione di una 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.
Terminata

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

un evento di trascinamento con il 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. Questa operazione viene eseguita indipendentemente dalla posizione in cui 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.

Ognuno di questi passaggi è descritto in modo più dettagliato nella sezione chiamata 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, i listener chiamano DragEvent.getAction(). Esistono sei possibili valori definiti da costanti nella classe DragEvent, descritti nella Tabella 1:

Tabella 1. Tipi di azione 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 evento che il listener riceve quando l'ombra di trascinamento entra nel riquadro di delimitazione.
ACTION_DRAG_LOCATION Dopo un ACTION_DRAG_ENTERED evento, l'ombra di trascinamento si trova ancora all'interno del riquadro di delimitazione del listener di eventi di trascinamento View.
ACTION_DRAG_EXITED Dopo un ACTION_DRAG_ENTERED e almeno un ACTION_DRAG_LOCATION evento, l'ombra di trascinamento si sposta all'esterno del riquadro di delimitazione del listener di eventi di trascinamento View.
ACTION_DROP L'ombra di trascinamento viene rilasciata sul listener di eventi di trascinamento View. Questo tipo di azione viene inviato al listener di un oggetto View solo se il listener restituisce il valore booleano true in risposta all' ACTION_DRAG_STARTED evento di trascinamento. 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 il valore booleano true se elabora correttamente il rilascio. 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 ACTION_DROP, la ricezione del tipo di azione ACTION_DRAG_ENDED non implica che il rilascio sia andato a buon fine. Il listener deve chiamare getResult(), come mostrato nella Tabella 2, per ottenere il valore restituito in risposta a ACTION_DROP. Se non viene inviato un ACTION_DROP evento, allora 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 azione, come riassunto nella Tabella 2. Per ulteriori informazioni sugli eventi e sui dati associati, vedi la sezione chiamata A 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.

Ombra di trascinamento

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 un aspetto dell'operazione di trascinamento.

L'immagine è chiamata ombra di trascinamento. Puoi crearla con i metodi dichiarati per un View.DragShadowBuilder oggetto. Passa 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 definiti in View.DragShadowBuilder per ottenere un'ombra di trascinamento.

La classe View.DragShadowBuilder ha due costruttori:

View.DragShadowBuilder(View)

Questo costruttore accetta qualsiasi oggetto View dell'applicazione. Il costruttore memorizza l'oggetto View nell'oggetto View.DragShadowBuilder, in modo che i callback possano accedervi per costruire l'ombra di trascinamento. La visualizzazione non deve essere una View selezionata dall'utente per avviare l'operazione di trascinamento.

Se utilizzi questo costruttore, non devi estendere View.DragShadowBuilder o sostituire i relativi metodi. Per impostazione predefinita, ottieni un'ombra di trascinamento con lo stesso aspetto della View passata come argomento, centrata sotto la posizione in cui l'utente tocca lo schermo.

View.DragShadowBuilder()

Se utilizzi questo costruttore, nell'oggetto View.DragShadowBuilder non è disponibile alcun oggetto View. Il campo è impostato su null. Devi estendere View.DragShadowBuilder e sostituire i relativi metodi, altrimenti ottieni un'ombra di trascinamento invisibile. 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 immediatamente 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 Point oggetto. La larghezza dell'ombra di trascinamento va in x e la sua altezza in y.

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

onDrawShadow()

Immediatamente 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 costruisce dai parametri forniti in onProvideShadowMetrics(). Il metodo disegna l'ombra di trascinamento sul Canvas fornito.

Per migliorare le prestazioni, mantieni le dimensioni dell'ombra di trascinamento ridotte. Per un singolo elemento, potresti utilizzare un'icona. Per una selezione di più elementi, potresti utilizzare le icone in una pila anziché immagini complete distribuite 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 visualizzazione. Quando il sistema chiama il metodo o il listener, fornisce un DragEvent argomento.

Nella maggior parte dei casi, è preferibile utilizzare un listener anziché il metodo di callback. Quando progetti le UI, in genere non crei sottoclassi delle classi View, ma l'utilizzo del metodo di callback ti costringe a creare sottoclassi per sostituire il metodo. Al contrario, puoi implementare una classe listener e poi utilizzarla con più oggetti View diversi. Puoi anche implementarla come classe inline anonima o espressione lambda. Per impostare il listener per un oggetto View, chiama setOnDragListener().

In alternativa, puoi modificare l'implementazione predefinita di onDragEvent() senza sostituire il metodo. Imposta un OnReceiveContentListener su una visualizzazione. Per maggiori dettagli, vedi setOnReceiveContentListener(). Il metodo onDragEvent() esegue quindi le seguenti operazioni per impostazione predefinita:

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

  • Restituisce true se i dati di trascinamento vengono rilasciati nella visualizzazione e OnReceiveContentListener utilizza parte dei contenuti.

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

Puoi avere un listener di eventi di trascinamento e un metodo di callback per un oggetto View. In questo 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 utilizzata con gli eventi touch.