Skip to content

Most visited

Recently visited

navigation

Arrastrar y soltar

Con el framework de arrastrar y soltar de Android, puedes permitir que tus usuarios muevan datos de un objeto View a otro del diseño actual mediante un gesto gráfico de arrastrar y soltar. El framework incluye una clase de eventos de arrastre, receptores de arrastre, y clases y métodos de ayuda.

Si bien el framework está principalmente diseñado para el movimiento de datos, puedes usarlo para otras acciones de la IU. Por ejemplo, podrías crear una app que combine colores cuando el usuario arrastre un ícono de color sobre otro ícono. No obstante, en el resto del tema se describe el framework con respecto al movimiento de datos.

Información general

Una operación de arrastrar y soltar comienza cuando el usuario hace algún gesto que reconoces como señal para iniciar el arrastre de datos. En respuesta a esto, tu aplicación indica al sistema que el arrastre está comenzando. El sistema vuelve a llamar a tu aplicación a fin de obtener una representación de los datos que se arrastran. A medida que el dedo del usuario mueve esta representación (una “sombra de arrastre”) sobre el diseño actual, el sistema envía eventos de arrastre a los objetos de receptores de eventos de arrastre y a los métodos de callback de eventos de arrastre asociados a los objetos View del diseño. Una vez que el usuario libera la sombra de arrastre, el sistema finaliza la operación de arrastre.

Debes crear un objeto de receptor de eventos de arrastre (“receptores”) a partir de una clase que implementa View.OnDragListener. Debes definir el objeto de receptor de eventos de arrastre para un objeto View con el método setOnDragListener() del objeto View. Cada objeto View también tiene un método de callback onDragEvent(). Estos dos elementos se describen con más detalle en la sección El receptor de eventos de arrastre y el método de callback.

Nota: Por razones de simplicidad, en las siguientes secciones, se hace referencia a la rutina que recibe los eventos de arrastre como “receptor de eventos de arrastre”, aunque en realidad pueda tratarse de un método de callback.

Cuando inicias un arrastre, debes incluir los datos que mueves y los metadatos que describen estos datos como parte de la llamada al sistema. Durante el arrastre, el sistema envía eventos de arrastre a los receptores de eventos de arrastre o métodos de callback de cada objeto View del diseño. Los receptores o métodos de callback pueden usar los metadatos para determinar si aceptan o no los datos cuando se sueltan. Si el usuario suelta los datos mediante un objeto View, y el receptor o método de callback del objeto View indica previamente al sistema que aceptará la acción de soltar, el sistema envía los datos al receptor o método de callback en un evento de arrastre.

Tu aplicación llama al método startDrag() para indicar al sistema que inicie un evento de arrastre. Esto notifica al sistema que comience a enviar eventos de arrastre. El método también envía los datos que arrastras.

Puedes llamar a startDrag() para acceder a cualquier objeto View adjunto del diseño actual. El sistema solo usa el objeto View para obtener acceso a la configuración global de tu diseño.

Una vez que tu aplicación llama a startDrag(), en el resto del proceso se usan eventos que el sistema envía a los objetos View de tu diseño actual.

El proceso de arrastrar y soltar

Básicamente, existen cuatro pasos o estados en el proceso de arrastrar y soltar:

Servicio iniciado
En respuesta al gesto de inicio de arrastre del usuario, tu aplicación llama a startDrag() para indicar al sistema que inicie un arrastre. Los argumentos startDrag() proporcionan los datos que se arrastrarán, los metadatos de estos y un callback para dibujar la sombra de arrastre.

En primer lugar, el sistema responde mediante un llamado a tu aplicación para obtener una sombra de arrastre. Luego, muestra la sombra de arrastre en el dispositivo.

A continuación, envía un evento de arrastre con el tipo de acción ACTION_DRAG_STARTED a los receptores del evento de arrastre de todos los objetos View del diseño actual. Para continuar recibiendo eventos de arrastre, incluido un posible evento de acción de soltar, un receptor de eventos de arrastre debe mostrar true. Esto registra el receptor en el sistema. Solo los receptores registrados continúan recibiendo eventos de arrastre. En este punto, los receptores también pueden cambiar la apariencia de su objeto View a fin de mostrar que el receptor puede aceptar un evento de acción de soltar.

Si el receptor de eventos de arrastre muestra false, no recibirá eventos de arrastre para la operación actual hasta que el sistema envíe un evento de arrastre con el tipo de acción ACTION_DRAG_ENDED. Al enviar false, el receptor indica al sistema que no está interesado en la operación de arrastre y que no aceptará los datos arrastrados.

Servicio continuado
El usuario continúa el arrastre. A medida que la sombra de arrastre intersecta el cuadro de límite de un objeto View, el sistema envía uno o más eventos de arrastre al receptor de eventos de arrastre del objeto View (si dicho receptor se encuentra registrado para recibir eventos). El receptor puede decidir modificar la apariencia su objeto View en respuesta al evento. Por ejemplo, si el evento indica que la sombra de arrastre ingresó en el cuadro de límite del objeto View (tipo de acción ACTION_DRAG_ENTERED), el receptor puede destacar su vista en respuesta a esto.
Servicio soltado
El usuario suelta la sombra de arrastre dentro del cuadro de límite de un objeto View que puede aceptar los datos. El sistema envía al receptor del objeto View un evento de arrastre con el tipo de acción ACTION_DROP. El evento de arrastre contiene los datos que se pasaron al sistema en la llamada a startDrag() que dio inicio a la operación. Se espera que el receptor muestre un booleano true al sistema si el código para aceptar el arrastre tiene éxito.

Ten en cuenta que este paso solo se realiza si el usuario suelta la sombra de arrastre dentro del cuadro de límite de un objeto View cuyo receptor se encuentre registrado para recibir eventos de arrastre. Si el usuario suelta la sombra de arrastre en otra situación, no se envían eventos de arrastre ACTION_DROP.

Servicio finalizado
Después de que el usuario suelta la sombra de arrastre y el sistema envía (si es necesario) un evento de arrastre con el tipo de acción ACTION_DROP, el sistema envía un evento de arrastre con el tipo de acción ACTION_DRAG_ENDED para indicar que la operación de arrastre ha finalizado. Esto se realiza independientemente del lugar en el cual el usuario haya liberado la sombra de arrastre. El evento se envía a todos los receptores que se encuentran registrados para recibir eventos de arrastre, incluso si estos receptores han recibido el evento ACTION_DROP.

Cada uno de estos cuatro pasos se describe con más detalle en la sección Diseño de una operación de arrastrar y soltar.

El receptor de eventos de arrastre y el método de callback

Un objeto View recibe eventos de arrastre con un receptor de eventos de arrastre que implementa View.OnDragListener o con su método de callback onDragEvent(DragEvent). Cuando el sistema llama al método o al receptor, les pasa un objeto DragEvent.

Probablemente te convenga usar el receptor en la mayoría de los casos. Cuando diseñas IU, por lo general, no creas una subclase de las clases de elementos View; más bien, el uso del método de callback te obliga a hacerlo a fin de anular el método. De manera comparativa, puedes implementar una clase de receptor y después usarlo con diferentes objetos View. También puedes implementarlo como clase integrada anónima. Para definir el receptor de un objeto View, llama a setOnDragListener().

Puedes tener un receptor y un método de callback para el objeto View. Si esto sucede, el sistema primero llama al receptor. El sistema no llama al método de callback a menos que el receptor muestre false.

La combinación del método onDragEvent(DragEvent) y el View.OnDragListener equivale a la combinación del onTouchEvent() y el View.OnTouchListener usados con eventos táctiles.

Eventos de arrastre

El sistema envía un evento de arrastre en forma de un objeto DragEvent. El objeto contiene un tipo de acción que informa al receptor lo que sucede en el proceso de arrastrar y soltar. El objeto incluye otros datos, según el tipo de acción.

Para obtener el tipo de acción, un receptor llama a getAction(). Existen seis valores posibles, definidos por constantes en la clase DragEvent. Estos se enumeran en la tabla 1.

El objeto DragEvent también contiene los datos que tu aplicación proporcionó al sistema en la llamada a startDrag(). Parte de los datos son válidos solamente para determinados tipos de acción. Los datos válidos para cada tipo de acción se resumen en la tabla 2. También se describen en detalle con el evento para el cual son válidos en la sección Diseño de una operación de arrastrar y soltar.

Tabla 1: Tipos de acciones DragEvent.

Valor getAction() Significado
ACTION_DRAG_STARTED Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos inmediatamente después de que la aplicación llama a startDrag() y obtiene una sombra de arrastre.
ACTION_DRAG_ENTERED Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos cuando la sombra de arrastre ingresa en el cuadro de límite del objeto View. Este es el primer tipo de acción de evento que recibe el receptor cuando la sombra de arrastre ingresa en el cuadro de límite. Si el receptor desea continuar recibiendo eventos de arrastre para esta operación, debe mostrar un booleano true al sistema.
ACTION_DRAG_LOCATION Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos después de recibir un evento ACTION_DRAG_ENTERED mientras la sombra de arrastre todavía se encuentra dentro del cuadro de límite de la Vista.
ACTION_DRAG_EXITED Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos después de recibir un evento ACTION_DRAG_ENTERED y al menos un evento ACTION_DRAG_LOCATION, y después de que el usuario mueve la sombra de arrastre fuera del cuadro de límite del objeto View.
ACTION_DROP Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos cuando el usuario suelta la sombra de arrastre sobre el objeto View. Este tipo de acción solo se envía a un receptor del objeto View si el receptor muestra un 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 sobre un objeto View cuyo receptor no se encuentre registrado o si suelta la sombra de arrastre sobre cualquier elemento que no forme parte del diseño actual.

Se espera que el receptor muestre un booleano true si procesa con éxito la acción de soltar. De lo contrario, debe mostrar false.

ACTION_DRAG_ENDED Un receptor de eventos de arrastre de un objeto View recibe este tipo de acción de eventos cuando el sistema finaliza la operación de arrastre. Este tipo de acción no necesariamente va precedida por un evento ACTION_DROP. Si el sistema envía un ACTION_DROP, la recepción del tipo de acción ACTION_DRAG_ENDED no implica que la operación de la acción de soltar haya tenido éxito. El receptor debe llamar a getResult() para obtener el valor que se mostró en respuesta a ACTION_DROP. Si no se envía un evento ACTION_DROP, getResult() muestra false.

Tabla 2: Datos de DragEvent válidos por tipo de acción.

Valor getAction() valor getClipDescription() valor getLocalState() valor getX() valor getY() valor getClipData() valor getResult()
ACTION_DRAG_STARTED X X X      
ACTION_DRAG_ENTERED X X X X    
ACTION_DRAG_LOCATION X X X X    
ACTION_DRAG_EXITED X X        
ACTION_DROP X X X X X  
ACTION_DRAG_ENDED X X       X

Los métodos 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 en particular, muestra null o 0, según su tipo de resultado.

La sombra de arrastre

Durante una operación de arrastrar y soltar, el sistema muestra una imagen que arrastra el usuario. En el caso del movimiento de datos, esta imagen representa los datos que se arrastran. Para las demás operaciones, la imagen representa algún aspecto de la operación de arrastre.

La imagen se denomina “sombra de arrastre”. Se crea con métodos que se declaran para un objeto View.DragShadowBuilder y después se pasa al sistema cuando inicias un arrastre con startDrag(). Como parte de su respuesta a startDrag(), el sistema invoca los métodos de callback definidos en View.DragShadowBuilder a fin de obtener una sombra de arrastre.

La clase View.DragShadowBuilder tiene dos constructores:

View.DragShadowBuilder(View)
Este constructor acepta cualquier objeto View de tu aplicación. El constructor almacena el objeto View en el objeto View.DragShadowBuilder, por lo cual, durante el callback puedes acceder a él a medida que construyes tu sombra de arrastre. No tiene que estar asociado al objeto View (si existe) que el usuario seleccionó para iniciar la operación de arrastre.

Si usas este constructor, no es necesario que amplíes View.DragShadowBuilder o anules sus métodos. Según la configuración predeterminada, obtendrás una sombra de arrastre con la misma apariencia que el objeto View que pasas como argumento, centrada debajo de la ubicación en la cual el usuario toca la pantalla.

View.DragShadowBuilder()
Si usas este constructor, no habrá disponibles objetos View en el objeto View.DragShadowBuilder (el campo se define en null). Si usas este constructor, y no amplías View.DragShadowBuilder ni anulas sus métodos, obtendrás una sombra de arrastre invisible. El sistema no muestra un error.

La clase View.DragShadowBuilder tiene dos métodos:

onProvideShadowMetrics()
El sistema llama a este método inmediatamente después de que llamas a startDrag(). Úsalo para enviar al sistema las dimensiones y el punto de contacto de la sombra de arrastre. Este método tiene dos argumentos:
dimensions
Objeto Point. El ancho de la sombra de arrastre se inserta en x y su altura se coloca en y.
touch_point
Objeto Point. El punto de contacto 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 en x y su posición Y va en y
onDrawShadow()
Inmediatamente después de la llamada a onProvideShadowMetrics(), el sistema llama a onDrawShadow() para obtener la sombra de arrastre propiamente dicha. El método tiene un argumento único, un objeto Canvas que el sistema construye a partir de los parámetros que proporcionas en onProvideShadowMetrics(). Úsalo para dibujar la sombra de arrastre en el objeto Canvas proporcionado.

A fin de mejorar el rendimiento, debes conservar un tamaño pequeño para la sombra de arrastre. En el caso de un elemento único, probablemente te convenga usar un ícono. Para una selección múltiple, se te recomienda usar íconos en una pila en lugar de imágenes completas desplegadas en la pantalla.

Diseño de una operación de arrastrar y soltar

En esta sección se muestra paso a paso la manera de iniciar un arrastre, responder a eventos durante este, responder a un evento de soltar, y finalizar la operación de arrastrar y soltar.

Inicio de un arrastre

El usuario inicia un arrastre con un gesto de arrastre; por lo general, mediante una pulsación prolongada en un objeto View. En respuesta, debes hacer lo siguiente:

  1. Según sea necesario, crea un objeto ClipData y ClipData.Item para los datos que mueves. Como parte del objeto ClipData, suministra metadatos que se almacenen en un objeto ClipDescription dentro de ClipData. En el caso de una operación de arrastrar y soltar que no represente movimientos de datos, es recomendable que uses null en lugar de un objeto real.

    Por ejemplo, en este fragmento de código se muestra la manera de responder a una pulsación prolongada en un elemento ImageView creando un objeto ClipData que contiene la etiqueta de un elemento ImageView. Después de este fragmento, el fragmento siguiente muestra la manera de anular los métodos en View.DragShadowBuilder:

    // Create a string for the ImageView label
    private static final String IMAGEVIEW_TAG = "icon bitmap"
    
    // Creates a new ImageView
    ImageView imageView = new ImageView(this);
    
    // Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
    imageView.setImageBitmap(mIconBitmap);
    
    // Sets the tag
    imageView.setTag(IMAGEVIEW_TAG);
    
        ...
    
    // Sets a long click listener for the ImageView using an anonymous listener object that
    // implements the OnLongClickListener interface
    imageView.setOnLongClickListener(new View.OnLongClickListener() {
    
        // Defines the one method for the interface, which is called when the View is long-clicked
        public boolean onLongClick(View v) {
    
        // Create a new ClipData.
        // This is done in two steps to provide clarity. The convenience method
        // ClipData.newPlainText() can create a plain text ClipData in one step.
    
        // Create a new ClipData.Item from the ImageView object's tag
        ClipData.Item item = new ClipData.Item(v.getTag());
    
        // Create a new ClipData using the tag as a label, the plain text MIME type, and
        // the already-created item. This will create a new ClipDescription object within the
        // ClipData, and set its MIME type entry to "text/plain"
        ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
    
        // Instantiates the drag shadow builder.
        View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
    
        // Starts the drag
    
                v.startDrag(dragData,  // the data to be dragged
                            myShadow,  // the drag shadow builder
                            null,      // no need to use local data
                            0          // flags (not currently used, set to 0)
                );
    
        }
    }
    
  2. El siguiente fragmento de código define myDragShadowBuilder. Crea una sombra de arrastre para arrastrar un elemento TextView como un pequeño rectángulo gris:
        private static class MyDragShadowBuilder extends View.DragShadowBuilder {
    
        // The drag shadow image, defined as a drawable thing
        private static Drawable shadow;
    
            // Defines the constructor for myDragShadowBuilder
            public MyDragShadowBuilder(View v) {
    
                // Stores the View parameter passed to myDragShadowBuilder.
                super(v);
    
                // Creates a draggable image that will fill the Canvas provided by the system.
                shadow = new ColorDrawable(Color.LTGRAY);
            }
    
            // Defines a callback that sends the drag shadow dimensions and touch point back to the
            // system.
            @Override
            public void onProvideShadowMetrics (Point size, Point touch) {
                // Defines local variables
                private int width, height;
    
                // Sets the width of the shadow to half the width of the original View
                width = getView().getWidth() / 2;
    
                // Sets the height of the shadow to half the height of the original View
                height = getView().getHeight() / 2;
    
                // The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
                // Canvas that the system will provide. As a result, the drag shadow will fill the
                // Canvas.
                shadow.setBounds(0, 0, width, height);
    
                // Sets the size parameter's width and height values. These get back to the system
                // through the size parameter.
                size.set(width, height);
    
                // Sets the touch point's position to be in the middle of the drag shadow
                touch.set(width / 2, height / 2);
            }
    
            // Defines a callback that draws the drag shadow in a Canvas that the system constructs
            // from the dimensions passed in onProvideShadowMetrics().
            @Override
            public void onDrawShadow(Canvas canvas) {
    
                // Draws the ColorDrawable in the Canvas passed in from the system.
                shadow.draw(canvas);
            }
        }
    

    Nota: Recuerda que no es necesario que amplíes View.DragShadowBuilder. El constructor View.DragShadowBuilder(View) crea una sombra de arrastre predeterminada del mismo tamaño que el argumento View que se pasó, con el punto de contacto centrado en la sombra de arrastre.

Respuesta a un inicio de arrastre

Durante la operación de arrastre, el sistema envía eventos de arrastre a los receptores de eventos de arrastre de los objetos View del diseño actual. Los receptores deben responder llamando a getAction() para obtener el tipo de acción. Al inicio del arrastre, este método muestra ACTION_DRAG_STARTED.

En respuesta a un evento con el tipo de acción ACTION_DRAG_STARTED, un receptor debe hacer lo siguiente:

  1. Llamar a getClipDescription() para obtener la ClipDescription. Usar los métodos de tipo de MIME en ClipDescription a fin de ver si el receptor puede aceptar los datos que se arrastran.

    Si la operación de arrastrar y soltar no representa ningún movimiento de datos, es posible que esta acción no sea necesaria.

  2. Si el receptor puede aceptar una acción de soltar, se debe mostrar true. Esto indica al sistema que continúe enviando eventos de arrastre al receptor. Si el receptor no puede aceptar una acción de soltar, debe mostrar false y el sistema detendrá el envío de eventos de arrastre hasta que se envíe ACTION_DRAG_ENDED.

Ten en cuenta que en el caso de un evento ACTION_DRAG_STARTED, los siguientes métodosDragEvent no son válidos: getClipData(), getX(), getY() y getResult().

Control de eventos durante el arrastre

Durante el arrastre, los receptores que muestran true en respuesta al evento de arrastre ACTION_DRAG_STARTED continúan recibiendo eventos de arrastre. Los tipos de eventos de arrastre que recibe un receptor durante el arrastre dependen de la ubicación de la sombra de arrastre y la visibilidad del objeto View del receptor.

Durante el arrastre, los receptores usan principalmente eventos de arrastre para determinar si deben cambiar la apariencia de su objeto View.

Durante el arrastre, getAction() muestra uno de estos tres valores:

No es necesario que el receptor responda a ninguno de estos tipos de acción. Si el receptor muestra un valor al sistema, dicho valor se ignora. A continuación, se describen algunas pautas para responder a cada uno de estos tipos de acción:

Respuesta a una acción de soltar

Cuando el usuario suelta la sombra de arrastre en un objeto View de la aplicación, y este informa anteriormente que puede aceptar el contenido arrastrado, el sistema envía el evento de arrastre a ese objeto View con el tipo de acción ACTION_DROP. El receptor debe hacer lo siguiente:

  1. Llamar a getClipData() para obtener el objeto ClipData suministrado originalmente en la llamada a startDrag() y almacenarlo. Si la operación de arrastrar y soltar no representa ningún movimiento de datos, es posible que esta acción no sea necesaria.
  2. Mostrar un booleano true para indicar que la acción de soltar se procesó con éxito o mostrar el booleano false si esto no sucedió. El valor mostrado se convierte en el valor que muestra getResult() para un evento ACTION_DRAG_ENDED.

    Ten en cuenta que, si el sistema no envía un evento ACTION_DROP, el valor de getResult() para un evento ACTION_DRAG_ENDED es false.

En el caso de un evento ACTION_DROP, getX() y getY() muestran la ubicación de X e Y del punto de arrastre al momento de la acción de soltar, mediante el sistema de coordenadas del objeto View que recibió la acción de soltar.

El sistema no permite que el usuario suelte la sombra de arrastre de un objeto View cuyo receptor no reciba eventos de arrastre. También permitirá al usuario soltar la sombra de arrastre en regiones vacías de la IU de la aplicación o en áreas fuera de tu aplicación. En todos estos casos, el sistema no envía un evento con el tipo de acción ACTION_DROP, aunque sí envía un evento ACTION_DRAG_ENDED.

Respuesta a una finalización de arrastre

Inmediatamente después de que el usuario suelta la sombra de arrastre, el sistema envía un evento de arrastre a todos los receptores de eventos de arrastre de tu aplicación, con un tipo de acción ACTION_DRAG_ENDED. Esto indica que la operación de arrastre ha finalizado.

Cada receptor debe hacer lo siguiente:

  1. Si el receptor cambió la apariencia de su objeto View durante la operación, deberá restablecer la apariencia predeterminada del objeto View. Se trata de una indicación visual que indica al usuario que la operación ha finalizado.
  2. Opcionalmente, el receptor puede llamar a getResult() a fin de obtener más información sobre la operación. Si un receptor mostró true en respuesta a un evento de tipo de acción ACTION_DROP, getResult() mostrará un booleano true. En todos los demás casos, getResult() muestra el booleano false, incluido cualquier caso en el cual el sistema no haya enviado un evento ACTION_DROP.
  3. El receptor debe mostrar al sistema el booleano true.

Respuesta a eventos de arrastre: ejemplo

Inicialmente, tu receptor o tu método de eventos de arrastre reciben todos los eventos de arrastre. El siguiente fragmento de código es un ejemplo simple de una respuesta a eventos de arrastre en un receptor:

// Creates a new drag event listener
mDragListen = new myDragEventListener();

View imageView = new ImageView(this);

// Sets the drag event listener for the View
imageView.setOnDragListener(mDragListen);

...

protected class myDragEventListener implements View.OnDragListener {

    // This is the method that the system calls when it dispatches a drag event to the
    // listener.
    public boolean onDrag(View v, DragEvent event) {

        // Defines a variable to store the action type for the incoming event
        final int action = event.getAction();

        // Handles each of the expected events
        switch(action) {

            case DragEvent.ACTION_DRAG_STARTED:

                // Determines if this View can accept the dragged data
                if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {

                    // As an example of what your application might do,
                    // applies a blue color tint to the View to indicate that it can accept
                    // data.
                    v.setColorFilter(Color.BLUE);

                    // Invalidate the view to force a redraw in the new tint
                    v.invalidate();

                    // returns true to indicate that the View can accept the dragged data.
                    return true;

                }

                // Returns false. During the current drag and drop operation, this View will
                // not receive events again until ACTION_DRAG_ENDED is sent.
                return false;

            case DragEvent.ACTION_DRAG_ENTERED:

                // Applies a green tint to the View. Return true; the return value is ignored.

                v.setColorFilter(Color.GREEN);

                // Invalidate the view to force a redraw in the new tint
                v.invalidate();

                return true;

            case DragEvent.ACTION_DRAG_LOCATION:

                // Ignore the event
                return true;

            case DragEvent.ACTION_DRAG_EXITED:

                // Re-sets the color tint to blue. Returns true; the return value is ignored.
                v.setColorFilter(Color.BLUE);

                // Invalidate the view to force a redraw in the new tint
                v.invalidate();

                return true;

            case DragEvent.ACTION_DROP:

                // Gets the item containing the dragged data
                ClipData.Item item = event.getClipData().getItemAt(0);

                // Gets the text data from the item.
                dragData = item.getText();

                // Displays a message containing the dragged data.
                Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);

                // Turns off any color tints
                v.clearColorFilter();

                // Invalidates the view to force a redraw
                v.invalidate();

                // Returns true. DragEvent.getResult() will return true.
                return true;

            case DragEvent.ACTION_DRAG_ENDED:

                // Turns off any color tinting
                v.clearColorFilter();

                // Invalidates the view to force a redraw
                v.invalidate();

                // Does a getResult(), and displays what happened.
                if (event.getResult()) {
                    Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);

                } else {
                    Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);

                }

                // returns true; the value is ignored.
                return true;

            // An unknown action type was received.
            default:
                Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
                break;
        }

        return false;
    }
};
This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.