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_STARTEDall'ascoltatore di eventi di trascinamento di tutti gli oggettiViewnel layout corrente. Per continuare a ricevere eventi di trascinamento, incluso un possibile evento di rilascio, l'ascoltatore di eventi di trascinamento deve restituiretrue. 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 dropViewper 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 azioneACTION_DRAG_ENDED. Restituiscefalse, 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
Viewin risposta all'evento. Ad esempio, se l'evento indica che l'ombra di trascinamento entra nell'area delimitata del target di rilascio (tipo di azioneACTION_DRAG_ENTERED), l'ascoltatore può reagire evidenziandoView. - 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 astartDragAndDrop()che avvia l'operazione. È previsto che il listener restituisca al sistema il valore booleanotruese elabora correttamente i dati eliminati. : questo passaggio si verifica solo se l'utente rilascia l'ombra di trascinamento all'interno del riquadro delimitante di unViewil 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 alcunACTION_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 azioneACTION_DRAG_ENDEDper 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'eventoACTION_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 |
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
Viewdella tua applicazione. Il costruttore memorizza l'oggettoViewnell'oggettoView.DragShadowBuilder, in modo che i callback possano accedervi per creare l'ombra della trascinamento. La visualizzazione non deve essere unViewselezionato dall'utente per avviare l'operazione di trascinamento.Se utilizzi questo costruttore, non devi estendere
View.DragShadowBuildero eseguire l'override dei suoi metodi. Per impostazione predefinita, viene visualizzata un'ombra di trascinamento che ha lo stesso aspetto diViewpassato come argomento, centrata sotto la posizione in cui l'utente tocca lo schermo.View.DragShadowBuilder()Se utilizzi questo costruttore, nell'oggetto
View.DragShadowBuildernon è disponibile alcun oggettoView. Il campo sia impostato sunull. Devi estendereView.DragShadowBuildere 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 oggettoPoint. La larghezza dell'ombra della trascinnata va inxe la sua altezza iny.outShadowTouchPoint: un oggettoPoint. 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 inxe la posizione Y iny.onDrawShadow()Immediatamente dopo la chiamata a
onProvideShadowMetrics(), il sistema chiamaonDrawShadow()per creare l'ombra trascinata. Il metodo ha un unico argomento, un oggettoCanvasche viene creato dal sistema a partire dai parametri forniti inonProvideShadowMetrics(). Il metodo disegna l'ombra di trascinamento sulCanvasfornito.
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 oggettoContentInfo. Il metodo richiamaOnReceiveContentListener.Restituisce true se i dati trascinati vengono rilasciati nella visualizzazione e se
OnReceiveContentListenerutilizza 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.