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 oggettiView
nel 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 dropView
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 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
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 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 booleanotrue
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 unView
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 alcunACTION_DROP
evento 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_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'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
View
della tua applicazione. Il costruttore memorizza l'oggettoView
nell'oggettoView.DragShadowBuilder
, in modo che i callback possano accedervi per creare l'ombra della trascinamento. La visualizzazione non deve essere unView
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 diView
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 oggettoView
. Il campo sia impostato sunull
. 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 oggettoPoint
. La larghezza dell'ombra della trascinnata va inx
e 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 inx
e 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 oggettoCanvas
che viene creato dal sistema a partire dai parametri forniti inonProvideShadowMetrics()
. Il metodo disegna l'ombra di trascinamento sulCanvas
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 oggettoContentInfo
. Il metodo richiamaOnReceiveContentListener
.Restituisce true se i dati trascinati vengono rilasciati nella visualizzazione e se
OnReceiveContentListener
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.