En las siguientes secciones, se explican algunos conceptos clave del proceso de arrastrar y soltar.
Proceso de arrastrar y soltar
El proceso de arrastrar y soltar tiene cuatro pasos o estados: iniciado, continuado, soltado y finalizado.
- Iniciado
En respuesta al gesto de arrastre de un usuario, tu aplicación llama a
startDragAndDrop()
para indicarle al sistema que inicie una operación de arrastrar y soltar. Los argumentos del método proporcionan lo siguiente:- Son los datos que se arrastrarán.
- Una devolución de llamada para dibujar la sombra de arrastre
- Metadatos que describen los datos arrastrados
- El sistema responde mediante una llamada a la app para obtener una sombra de arrastre. Luego, muestra la sombra de arrastre en el dispositivo.
- A continuación, el sistema envía un evento de arrastre con el tipo de acción
ACTION_DRAG_STARTED
al objeto de escucha de eventos de arrastre de todos los objetosView
del diseño actual. Para seguir recibiendo eventos de arrastre, incluido un posible evento de soltar, el objeto de escucha de evento de arrastre debe mostrartrue
. Esto registra el objeto de escucha con el sistema. Solo los objetos de escucha registrados siguen recibiendo eventos de arrastre. En este punto, los objetos de escucha también pueden cambiar el aspecto de su objetoView
del destino para soltar a fin de mostrar que el objeto View puede aceptar un evento de soltar. - Si el objeto de escucha de eventos de arrastre muestra
false
, no recibe eventos de arrastre para la operación actual hasta que el sistema envía un evento de arrastre con el tipo de acciónACTION_DRAG_ENDED
. Cuando muestrafalse
, el objeto de escucha le indica al sistema que no le interesa la operación de arrastrar y soltar, y que no quiere aceptar los datos arrastrados.
- Continuando
- El usuario continúa con el arrastre. A medida que la sombra de arrastre se cruza con el cuadro de límite de un destino para soltar, el sistema envía uno o más eventos de arrastre al objeto de escucha de eventos de arrastre del destino. El objeto de escucha puede alterar el aspecto del destino para soltar
View
en respuesta al evento. Por ejemplo, si el evento indica que la sombra de arrastre ingresó en el cuadro de límite del destino para soltar (tipo de acciónACTION_DRAG_ENTERED
), el objeto de escucha puede reaccionar destacandoView
. - Soltado
- El usuario suelta la sombra de arrastre dentro del cuadro de límite de un destino para soltar. El sistema envía al objeto de escucha del destino para soltar un evento de arrastre con el tipo de acción
ACTION_DROP
. El objeto del evento de arrastre contiene los datos que se pasan al sistema en la llamada astartDragAndDrop()
que inicia la operación. Se espera que el objeto de escucha muestre el valor booleanotrue
al sistema si procesa correctamente los datos soltados. : Este paso solo se produce si el usuario suelta la sombra de arrastre dentro del cuadro de límite de un elementoView
cuyo objeto de escucha está registrado para recibir eventos de arrastre (un destino para soltar). Si el usuario suelta la sombra de arrastre en cualquier otra situación, no se envía ningún evento de arrastreACTION_DROP
. - Finalizado
Después de que el usuario suelta la sombra de arrastre y el sistema envía
un evento de arrastre con un tipo de acción
ACTION_DROP
, si es necesario, el sistema envía un evento de arrastre con un tipo de acciónACTION_DRAG_ENDED
para indicar que la operación de arrastrar y soltar terminó. Esto se lleva a cabo sin importar dónde liberó la sombra de arrastre el usuario. El evento se envía a todos los objetos de escucha que están registrados para recibir eventos de arrastre, incluso si también recibieron el eventoACTION_DROP
.
Cada uno de estos pasos se describe con más detalle en la sección Una operación de arrastrar y soltar.
Eventos de arrastre
El sistema envía un evento de arrastre en forma de objeto DragEvent
, que contiene un tipo de acción que describe lo que sucede en el proceso de arrastrar y soltar. Según el tipo de acción, el objeto también puede contener otros datos.
Los objetos de escucha de eventos de arrastre reciben el objeto DragEvent
. Para obtener el tipo de acción, los objetos de escucha llaman a DragEvent.getAction()
.
Hay seis valores posibles, definidos por constantes en la clase DragEvent
, que se describen en la tabla 1:
Tabla 1: Tipos de acción DragEvent
Tipo de acción | Significado |
---|---|
ACTION_DRAG_STARTED |
La aplicación llama a startDragAndDrop() y obtiene una sombra de arrastre. Si el objeto de escucha quiere seguir recibiendo eventos de arrastre para esta operación, debe mostrar un valor booleano true en el sistema.
|
ACTION_DRAG_ENTERED |
La sombra de arrastre ingresa al cuadro de límite del elemento View del objeto de escucha de eventos de arrastre. Este es el primer tipo de acción de evento que recibe el objeto de escucha cuando la sombra de arrastre ingresa al cuadro de límite.
|
ACTION_DRAG_LOCATION |
Luego de un evento de ACTION_DRAG_ENTERED , la sombra de arrastre permanece dentro del cuadro de límite del elemento View del objeto de escucha de eventos de arrastre.
|
ACTION_DRAG_EXITED |
Después de un evento de ACTION_DRAG_ENTERED y al menos un evento de ACTION_DRAG_LOCATION , la sombra de arrastre se mueve fuera del cuadro de límite del elemento View del objeto de escucha de eventos de arrastre.
|
ACTION_DROP |
La sombra de arrastre se suelta sobre el elemento View del objeto de escucha de eventos de arrastre. Este tipo de acción solo se envía al objeto de escucha de un objeto View si el objeto de escucha mostró un valor booleano true en respuesta al evento de arrastre ACTION_DRAG_STARTED . Este tipo de acción no se envía si el usuario suelta la sombra de arrastre en un elemento View cuyo objeto de escucha no está registrado o si suelta la sombra de arrastre sobre cualquier elemento que no sea parte del diseño actual.
El objeto de escucha muestra un valor booleano |
ACTION_DRAG_ENDED |
El sistema está finalizando la operación de arrastrar y soltar. Este tipo de acción no necesariamente está precedido por un evento ACTION_DROP . Si el sistema envía un ACTION_DROP , recibir el tipo de acción ACTION_DRAG_ENDED no implica que la operación de soltar se haya realizado correctamente. El objeto de escucha debe llamar a getResult() , como se muestra en la tabla 2, para obtener el valor que se muestra en respuesta a ACTION_DROP . Si no se envía un evento ACTION_DROP , getResult() muestra false .
|
El objeto DragEvent
también contiene los datos y metadatos que tu aplicación proporciona al sistema en la llamada a startDragAndDrop()
. Algunos de los datos son válidos solo para determinados tipos de acciones, como se resume en la tabla 2. Para obtener más información sobre los eventos y sus datos asociados, consulta la sección Una operación de arrastrar y soltar.
Tabla 2: Datos válidos de DragEvent por tipo de acción
ValorgetAction() |
ValorgetClipDescription() |
ValorgetLocalState() |
ValorgetX() |
ValorgetY() |
ValorgetClipData() |
ValorgetResult() |
---|---|---|---|---|---|---|
ACTION_DRAG_STARTED |
✓ | ✓ | ||||
ACTION_DRAG_ENTERED |
✓ | ✓ | ||||
ACTION_DRAG_LOCATION |
✓ | ✓ | ✓ | ✓ | ||
ACTION_DRAG_EXITED |
✓ | ✓ | ||||
ACTION_DROP |
✓ | ✓ | ✓ | ✓ | ✓ | |
ACTION_DRAG_ENDED |
✓ | ✓ |
Los métodos DragEvent
getAction()
,
describeContents()
,
writeToParcel()
y
toString()
siempre muestran datos válidos.
Si un método no contiene datos válidos para un tipo de acción específico, muestra null
o 0, según su tipo de resultado.
Sombra de arrastre
Durante una operación de arrastrar y soltar, el sistema muestra una imagen que el usuario arrastra. Para el movimiento de datos, esta imagen representa los datos que se arrastran. Para otras operaciones, la imagen representa algún aspecto de la operación de arrastre.
La imagen se llama sombra de arrastre. Se crea con métodos que declaras para un objeto View.DragShadowBuilder
. Para pasar el compilador al sistema cuando inicies una operación de arrastrar y soltar, usa startDragAndDrop()
. Como parte de la respuesta a startDragAndDrop()
, el sistema invoca los métodos de devolución de llamada que defines en View.DragShadowBuilder
para obtener una sombra de arrastre.
La clase View.DragShadowBuilder
tiene dos constructores:
View.DragShadowBuilder(View)
Este constructor acepta cualquiera de los objetos
View
de la aplicación. El constructor almacena el objetoView
en el objetoView.DragShadowBuilder
, por lo que las devoluciones de llamada pueden acceder a él para construir la sombra de arrastre. No es necesario que la vista sea unView
que el usuario seleccione para iniciar la operación de arrastre.Si usas este constructor, no necesitas extender
View.DragShadowBuilder
ni anular sus métodos. De forma predeterminada, obtienes una sombra de arrastre que tiene el mismo aspecto que el elementoView
que pasas como argumento, centrada debajo de la ubicación en la que el usuario toca la pantalla.View.DragShadowBuilder()
Si usas este constructor, no habrá objetos
View
disponibles en el objetoView.DragShadowBuilder
. El campo se establece comonull
. Debes extenderView.DragShadowBuilder
y anular sus métodos; de lo contrario, obtendrás una sombra de arrastre invisible. El sistema no arroja un error.
La clase View.DragShadowBuilder
tiene dos métodos que, en conjunto, crean la sombra de arrastre:
onProvideShadowMetrics()
El sistema llama a este método inmediatamente después de que llamas a
startDragAndDrop()
. Usa el método para enviar las dimensiones y el punto táctil de la sombra de arrastre al sistema. El método tiene dos parámetros:outShadowSize
: Un objetoPoint
. El ancho de la sombra de arrastre va enx
y su altura va eny
.outShadowTouchPoint
: Un objetoPoint
. El punto táctil es la ubicación dentro de la sombra de arrastre que debe estar debajo del dedo del usuario durante el arrastre. Su posición X va enx
y su posición Y va eny
.onDrawShadow()
Inmediatamente después de la llamada a
onProvideShadowMetrics()
, el sistema llama aonDrawShadow()
para crear la sombra de arrastre. El método tiene un solo argumento, un objetoCanvas
que el sistema construye a partir de los parámetros que proporcionas enonProvideShadowMetrics()
. El método dibuja la sombra de arrastre en elCanvas
proporcionado.
Para mejorar el rendimiento, mantén el tamaño de la sombra de arrastre pequeño. Para un solo elemento, te recomendamos que uses un ícono. Para una selección múltiple, te recomendamos que uses íconos en una pila en lugar de imágenes completas distribuidas en la pantalla.
Objetos de escucha de eventos de arrastre y métodos de devolución de llamada
Un View
recibe eventos de arrastre con un objeto de escucha de eventos de arrastre que implementa View.OnDragListener
o con el método de devolución de llamada onDragEvent()
de la vista. Cuando el sistema llama al método o al objeto de escucha, proporciona un argumento DragEvent
.
En la mayoría de los casos, es preferible usar un objeto de escucha que usar el método de devolución de llamada. Cuando se diseñan IU, por lo general, no se crean subclases de clases View
, pero el uso del método de devolución de llamada te obliga a crear subclases para anular el método. En comparación, puedes implementar una clase de objeto de escucha y, luego, usarla con varios objetos View
diferentes. También puedes implementarlo como una clase intercalada anónima o una expresión lambda. Para configurar el objeto de escucha de un objeto View
, llama a setOnDragListener()
.
Como alternativa, puedes alterar la implementación predeterminada de onDragEvent()
sin anular el método. Establece un OnReceiveContentListener
en una vista. Para obtener más información, consulta setOnReceiveContentListener()
.
Luego, el método onDragEvent()
hace lo siguiente de forma predeterminada:
- Devuelve verdadero en respuesta a la llamada a
startDragAndDrop()
. Llama a
performReceiveContent()
si los datos de la función de arrastrar y soltar se sueltan en la vista. Los datos se pasan al método como un objetoContentInfo
. El método invoca aOnReceiveContentListener
.El resultado es verdadero si los datos de la función de arrastrar y soltar se sueltan en la vista y el objeto
OnReceiveContentListener
consume el contenido.
Define el objeto OnReceiveContentListener
para controlar los datos específicos de tu app. Para obtener una retrocompatibilidad hasta el nivel de API 24, usa la versión de Jetpack de OnReceiveContentListener
.
Puedes tener un objeto de escucha de eventos de arrastre y un método de devolución de llamada para un objeto View
, en cuyo caso el sistema primero llama al objeto de escucha. El sistema no llama al método de devolución de llamada a menos que el objeto de escucha muestre false
.
La combinación del método onDragEvent()
y View.OnDragListener
es análoga a la combinación de onTouchEvent()
y View.OnTouchListener
que se usa con los eventos táctiles.