Concetti fondamentali

Prova la funzionalità Scrivi
Jetpack Compose è il toolkit per l'interfaccia utente consigliato per Android. Scopri come utilizzare il trascinamento in Compose.

Le sezioni seguenti spiegano alcuni concetti chiave per la procedura di trascinamento.

Procedura di trascinamento

Il processo di trascinamento prevede quattro passaggi o stati: iniziato, in corso, rilasciato 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 forniscono quanto segue:

  • I dati da trascinare.
  • Un callback per disegnare l'ombra di trascinamento
  • Metadati che descrivono i dati trascinati
  • Il sistema risponde richiamando la tua applicazione per ottenere un'ombra di trascinamento. Il sistema mostra quindi l'ombra di trascinamento 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 gli oggetti View nel layout corrente. Per continuare a ricevere eventi di trascinamento, incluso un possibile evento di rilascio, l'ascoltatore di eventi di trascinamento deve restituire true. In questo modo, il listener viene registrato nel sistema. Solo gli ascoltatori registrati continuano a ricevere eventi di trascinamento. A questo punto, gli ascoltatori possono anche modificare l'aspetto dell'oggetto destinazione del drop View per indicare che la visualizzazione può accettare un evento drop.
  • Se l'ascoltatore 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 tipo di azione ACTION_DRAG_ENDED. Restituisce false, l'ascoltatore 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 della trascinnata interseca la delimitazione di un target di rilascio, il sistema invia uno o più eventi di trascinamento all'ascoltatore di eventi di trascinamento del target. L'ascoltatore potrebbe modificare l'aspetto del target di inserimento View in risposta all'evento. Ad esempio, se l'evento indica che l'ombra di trascinamento entra nell'area delimitata del target di rilascio (tipo di azione ACTION_DRAG_ENTERED), l'ascoltatore può reagire evidenziando View.
Interrotto
L'utente rilascia l'ombra di trascinamento all'interno del riquadro delimitante di un target di rilascio. Il sistema invia all'ascoltatore del target di rilascio un evento di trascinamento con tipo di azione ACTION_DROP. L'oggetto evento di trascinamento contiene i dati che vengono passati al sistema nella chiamata a startDragAndDrop() che avvia l'operazione. È previsto che il listener restituisca al sistema il valore booleano true se elabora correttamente i dati eliminati. : questo passaggio si verifica solo se l'utente rilascia l'ombra di trascinamento all'interno del riquadro delimitante di un View il cui ascoltatore è registrato per ricevere eventi di trascinamento (un target di rilascio). Se l'utente rilascia l'ombra di trascinamento in un'altra situazione, non viene inviato alcun ACTION_DROPevento di trascinamento
.
Terminato

Dopo che l'utente rilascia l'ombra di trascinamento 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 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 tutti gli ascoltatori registrati per ricevere eventi di trascinamento, anche se l'ascoltatore 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 nella procedura 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 dalle 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 trascinata. Se l'ascoltatore vuole continuare a ricevere eventi di trascinamento per questa operazione, deve restituire un valore booleano true al sistema.
ACTION_DRAG_ENTERED L'ombra di trascinamento entra nell'area delimitata di View dell'ascoltatore di eventi di trascinamento. Questo è il primo tipo di azione evento ricevuto dall'ascoltatore quando l'ombra di trascinamento entra nell'area delimitata.
ACTION_DRAG_LOCATION In seguito a un evento ACTION_DRAG_ENTERED, l'ombra di trascinamento è ancora all'interno del riquadro delimitante del valore View del listener di eventi di trascinamento.
ACTION_DRAG_EXITED Dopo un evento ACTION_DRAG_ENTERED e almeno un evento ACTION_DRAG_LOCATION, l'ombra di trascinamento si sposta all'esterno del riquadro delimitante del View dell'ascoltatore di eventi di trascinamento.
ACTION_DROP L'ombra del trascinamento viene rilasciata sopra il View del listener di eventi di trascinamento. Questo tipo di azione viene inviato all'ascoltatore di un oggetto View solo se l'ascoltatore restituisce un 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 di cui l'ascoltatore non è registrato o se l'utente rilascia l'ombra di trascinamento su un elemento che non fa parte del layout corrente.

L'ascoltatore restituisce true booleano se elabora correttamente il drop. 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 drop sia andato a buon fine. L'ascoltatore 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 la tua applicazione fornisce al sistema nella chiamata a startDragAndDrop(). Alcuni dati sono validi solo per determinati tipi di azioni, come descritto nella tabella 2. Per ulteriori informazioni sugli eventi e sui dati associati, consulta la sezione Un'operazione di trascinamento.

Tabella 2. Dati DragEvent validi per tipo di azione

getAction()
value
getClipDescription()
value
getLocalState()
value
getX()
value
getY()
value
getClipData()
value
getResult()
value
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() sempre restituiranno dati validi.

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

Ombra di trascinamento

Durante un'operazione di trascinamento, il sistema mostra un'immagine che l'utente trascina. Per il movimento dei dati, questa immagine rappresenta i dati trascinati. Per altre operazioni, l'immagine rappresenta un aspetto dell'operazione di trascinamento.

L'immagine è chiamata ombra trascinata. Lo crei con i metodi dichiarati per un oggetto View.DragShadowBuilder. Trasmetti il generatore al sistema quando avvii un'operazione di trascinamento utilizzando startDragAndDrop(). Nell'ambito della risposta a startDragAndDrop(), il sistema invoca i metodi di callback che definisci 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 della tua applicazione. Il costruttore memorizza l'oggetto View nell'oggetto View.DragShadowBuilder, in modo che i callback possano accedervi per creare l'ombra della trascinamento. La visualizzazione non deve essere un View selezionato dall'utente per avviare l'operazione di trascinamento.

Se utilizzi questo costruttore, non devi estendere View.DragShadowBuilder o eseguire l'override dei suoi metodi. Per impostazione predefinita, viene visualizzata un'ombra di trascinamento che ha lo stesso aspetto di View passato 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 sia impostato su null. Devi estendereView.DragShadowBuilder e sostituire i relativi metodi, altrimenti otterrai 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 della trascinnata al sistema. Il metodo ha due parametri:

outShadowSize: un oggetto Point. La larghezza dell'ombra della trascinnata 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 trascinata. Il metodo ha un unico argomento, un oggetto Canvas che viene creato dal sistema a partire dai parametri forniti in onProvideShadowMetrics(). Il metodo disegna l'ombra di trascinamento sul Canvas fornito.

Per migliorare le prestazioni, mantieni piccole le dimensioni dell'ombra trascinata. Per un singolo elemento, ti consigliamo di utilizzare un'icona. Per una selezione di più elementi, potresti scegliere di utilizzare icone in una serie anziché immagini complete distribuite sullo schermo.

Trascina i listener di eventi e i 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 l'ascoltatore, fornisce un argomento DragEvent.

Nella maggior parte dei casi, è preferibile utilizzare un ascoltatore rispetto al metodo di callback. Quando progetti UI, in genere non crei sottoclassi delle classi View, ma l'utilizzo del metodo callback ti obbliga a creare sottoclassi per eseguire l'override del metodo. In confronto, puoi implementare una classe di listener e utilizzarla con più oggetti View diversi. Puoi anche implementarlo come classe anonima in linea o espressione lambda. Per impostare l'ascoltatore per un oggetto View, chiama setOnDragListener().

In alternativa, puoi modificare l'implementazione predefinita di onDragEvent() senza eseguire l'override del metodo. Imposta un OnReceiveContentListener in una visualizzazione. Per maggiori dettagli, consulta setOnReceiveContentListener(). Per impostazione predefinita, il metodo onDragEvent() esegue le seguenti operazioni:

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

  • Restituisce true se i dati trascinati vengono rilasciati nella visualizzazione e seOnReceiveContentListener utilizza uno dei contenuti.

Definisci 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, nel quale caso il sistema chiama prima il listener. Il sistema non chiama il metodo callback a meno che l'ascoltatore non restituisca false.

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