drag-drop.jd revision dd05f1812ee86bc8c6176c9dbd30aae8fe0db8b8
1page.title=Dragging and Dropping
2@jd:body
3<div id="qv-wrapper">
4    <div id="qv">
5        <h2>Quickview</h2>
6            <ul>
7                <li>
8                    Allow users to move data within your Activity layout using graphical gestures.
9                </li>
10                <li>
11                    Supports operations besides data movement.
12                </li>
13                <li>
14                    Only works within a single application.
15                </li>
16                <li>
17                    Requires API 11.
18                </li>
19            </ul>
20        <h2>In this document</h2>
21        <ol>
22            <li>
23                <a href="#AboutDragging">Overview</a>
24                <ol>
25                    <li>
26                        <a href="#DragDropLifecycle">The drag/drop process</a>
27                    </li>
28                    <li>
29                        <a href="#AboutDragListeners">The drag event listener and callback method</a>
30                    </li>
31                    <li>
32                        <a href="#AboutDragEvent">Drag events</a>
33                    </li>
34                    <li>
35                        <a href="#AboutDragShadowBuilder">
36                        The drag shadow</a>
37                    </li>
38                </ol>
39            </li>
40            <li>
41                <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>
42                <ol>
43                    <li>
44                        <a href="#StartDrag">Starting a drag</a>
45                    </li>
46                    <li>
47                        <a href="#HandleStart">Responding to a drag start</a>
48                    </li>
49                    <li>
50                        <a href="#HandleDuring">Handling events during the drag</a>
51                    </li>
52                    <li>
53                        <a href="#HandleDrop">Responding to a drop</a>
54                    </li>
55                    <li>
56                        <a href="#HandleEnd">Responding to a drag end</a>
57                    </li>
58                    <li>
59                        <a href="#RespondEventSample">Responding to drag events: an example</a>
60                    </li>
61                </ol>
62            </li>
63        </ol>
64        <h2>Key classes</h2>
65        <ol>
66            <li>
67                {@link android.view.View View}
68            </li>
69            <li>
70                {@link android.view.View.OnLongClickListener OnLongClickListener}
71            </li>
72            <li>
73                {@link android.view.View.OnDragListener OnDragListener}
74            </li>
75            <li>
76                {@link android.view.DragEvent DragEvent}
77            </li>
78            <li>
79                {@link android.view.View.DragShadowBuilder DragShadowBuilder}
80            </li>
81            <li>
82                {@link android.content.ClipData ClipData}
83            </li>
84            <li>
85                {@link android.content.ClipDescription ClipDescription}
86            </li>
87        </ol>
88        <h2>Related Samples</h2>
89        <ol>
90            <li>
91                <a href="{@docRoot}resources/samples/Honeycomb-Gallery/index.html">
92                Honeycomb-Gallery</a> sample application.
93            </li>
94            <li>
95                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DragAndDropDemo.html">
96DragAndDropDemo.java</a> and
97                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DraggableDot.html">
98DraggableDot.java</a> in <a href="{@docRoot}resources/samples/ApiDemos/index.html">Api Demos</a>.
99            </li>
100        </ol>
101        <h2>See also</h2>
102        <ol>
103            <li>
104            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
105            </li>
106            <li>
107                <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
108            </li>
109        </ol>
110    </div>
111</div>
112<p>
113    With the Android drag/drop framework, you can allow your users to move data
114    from one View to another View in the current layout using a graphical drag and drop gesture.
115    The framework includes a drag event class, drag listeners, and helper methods and classes.
116</p>
117<p>
118    Although the framework is primarily designed for data movement, you can use
119    it for other UI actions. For example, you could create an app that mixes colors when the user
120    drags a color icon over another icon. The rest of this topic, however, describes the
121    framework in terms of data movement.
122</p>
123<h2 id="AboutDragging">Overview</h2>
124<p>
125    A drag and drop operation starts when the user makes some gesture that you recognize as a
126    signal to start dragging data. In response, your application tells the system that the drag is
127    starting. The system calls back to your application to get a representation of the data
128    being dragged. As the user's finger moves this representation (a &quot;drag shadow&quot;)
129    over the current layout, the system sends drag events to the drag event listener objects and
130    drag event callback methods associated with the {@link android.view.View} objects in the layout.
131    Once the user releases the drag shadow, the system ends the drag operation.
132</p>
133<p>
134    You create a drag event listener object (&quot;listeners&quot;) from a class that implements
135    {@link android.view.View.OnDragListener}. You set the drag event listener object for a View
136    with the View object's
137    {@link android.view.View#setOnDragListener(View.OnDragListener) setOnDragListener()} method.
138    Each View object also has a {@link android.view.View#onDragEvent(DragEvent) onDragEvent()}
139    callback method. Both of these are described in more detail in the section
140    <a href="#AboutDragListeners">The drag event listener and callback method</a>.
141</p>
142<p class="note">
143    <strong>Note</strong>: For the sake of simplicity, the following sections refer to the routine
144    that receives drag events as the &quot;drag event listener&quot;, even though it may actually
145    be a callback method.
146</p>
147<p>
148    When you start a drag, you include both the data you are moving and metadata describing this
149    data as part of the call to the system. During the drag, the system sends drag events to the
150    drag event listeners or callback methods of each View in the layout. The listeners or callback
151    methods can use the metadata to decide if they want to accept the data when it is dropped.
152    If the user drops the data over a View object, and that View object's listener or callback
153    method has previously told the system that it wants to accept the drop, then the system sends
154    the data to the listener or callback method in a drag event.
155</p>
156<p>
157    Your application tells the system to start a drag by calling the
158    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
159    method. This tells the system to start sending drag events. The method also sends the data that
160    you are dragging.
161</p>
162<p>
163    You can call
164    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
165    for any attached View in the current layout. The system only uses the View object to get access
166    to global settings in your layout.
167</p>
168<p>
169    Once your application calls
170    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
171    the rest of the process uses events that the system sends to the View objects in your current
172    layout.
173</p>
174<h3 id="DragDropLifecycle">The drag/drop process</h3>
175<p>
176    There are basically four steps or states in the drag and drop process:
177</p>
178<dl>
179    <dt>
180        <em>Started</em>
181    </dt>
182    <dd>
183        In response to the user's gesture to begin a drag, your application calls
184        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
185        to tell the system to start a drag. The arguments
186        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
187        provide the data to be dragged, metadata for this data, and a callback for drawing the
188        drag shadow.
189        <p>
190            The system first responds by calling back to your application to get a drag shadow. It
191            then displays the drag shadow on the device.
192        </p>
193        <p>
194            Next, the system sends a drag event with action type
195            {@link android.view.DragEvent#ACTION_DRAG_STARTED} to the drag event listeners for
196            all the View objects in the current layout. To continue to receive drag events,
197            including a possible drop event, a drag event listener must return <code>true</code>.
198            This registers the listener with the system. Only registered listeners continue to
199            receive drag events. At this point, listeners can also change the appearance of their
200            View object to show that the listener can accept a drop event.
201        </p>
202        <p>
203            If the drag event listener returns <code>false</code>, then it will not receive drag
204            events for the current operation until the system sends a drag event with action type
205            {@link android.view.DragEvent#ACTION_DRAG_ENDED}. By sending <code>false</code>, the
206            listener tells the system that it is not interested in the drag operation and
207            does not want to accept the dragged data.
208        </p>
209    </dd>
210    <dt>
211        <em>Continuing</em>
212    </dt>
213    <dd>
214        The user continues the drag. As the drag shadow intersects the bounding box of a View
215        object, the system sends one or more drag events to the View object's drag event
216        listener (if it is registered to receive events). The listener may choose to
217        alter its View object's appearance in response to the event. For example, if the event
218        indicates that the drag shadow has entered the bounding box of the View
219        (action type {@link android.view.DragEvent#ACTION_DRAG_ENTERED}), the listener
220        can react by highlighting its View.
221    </dd>
222    <dt>
223        <em>Dropped</em>
224    </dt>
225    <dd>
226        The user releases the drag shadow within the bounding box of a View that can accept the
227        data. The system sends the View object's listener a drag event with action type
228        {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was
229        passed to the system in the call to
230        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
231        that started the operation. The listener is expected to return boolean <code>true</code> to
232        the system if code for accepting the drop succeeds.
233        <p>
234            Note that this step only occurs if the user drops the drag shadow within the bounding
235            box of a View whose listener is registered to receive drag events. If the user releases
236            the drag shadow in any other situation, no {@link android.view.DragEvent#ACTION_DROP}
237            drag event is sent.
238        </p>
239    </dd>
240    <dt>
241        <em>Ended</em>
242    </dt>
243    <dd>
244        After the user releases the drag shadow, and after the system sends out (if necessary)
245        a drag event with action type {@link android.view.DragEvent#ACTION_DROP}, the system sends
246        out a drag event with action type {@link android.view.DragEvent#ACTION_DRAG_ENDED} to
247        indicate that the drag operation is over. This is done regardless of where the user released
248        the drag shadow. The event is sent to every listener that is registered to receive drag
249        events, even if the listener received the {@link android.view.DragEvent#ACTION_DROP} event.
250    </dd>
251</dl>
252<p>
253    Each of these four steps is described in more detail in the section
254    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
255</p>
256<h3 id="AboutDragListeners">The drag event listener and callback method</h3>
257<p>
258    A View receives drag events with either a drag event listener that implements
259    {@link android.view.View.OnDragListener} or with its
260    {@link android.view.View#onDragEvent(DragEvent)} callback method.
261    When the system calls the method or listener, it passes to them
262    a {@link android.view.DragEvent} object.
263</p>
264<p>
265    You will probably want to use the listener in most cases. When you design UIs, you usually
266    don't subclass View classes, but using the callback method forces you to do this in order to
267    override the method. In comparison, you can implement one listener class and then use it with
268    several different View objects. You can also implement it as an anonymous inline class. To
269    set the listener for a View object, call
270{@link android.view.View#setOnDragListener(android.view.View.OnDragListener) setOnDragListener()}.
271</p>
272<p>
273    You can have both a listener and a callback method for View object. If this occurs,
274    the system first calls the listener. The system doesn't call the callback method unless the
275    listener returns <code>false</code>.
276</p>
277<p>
278    The combination of the {@link android.view.View#onDragEvent(DragEvent)} method and
279    {@link android.view.View.OnDragListener} is analogous to the combination
280    of the {@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()} and
281    {@link android.view.View.OnTouchListener} used with touch events.
282</p>
283<h3 id="AboutDragEvent">Drag events</h3>
284<p>
285    The system sends out a drag event in the form of a {@link android.view.DragEvent} object. The
286    object contains an action type that tells the listener what is happening in the drag/drop
287    process. The object contains other data, depending on the action type.
288</p>
289<p>
290    To get the action type, a listener calls {@link android.view.DragEvent#getAction()}. There
291    are six possible values, defined by constants in the {@link android.view.DragEvent} class. These
292    are listed in <a href="table1">table 1</a>.
293</p>
294<p>
295    The {@link android.view.DragEvent} object also contains the data that your application provided
296    to the system in the call to
297    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
298    Some of the data is valid only for certain action types. The data that is valid for each action
299    type is summarized in <a href="table2">table 2</a>. It is also described in detail with
300    the event for which it is valid in the section
301    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
302</p>
303<p class="table-caption" id="table1">
304  <strong>Table 1.</strong> DragEvent action types
305</p>
306<table>
307    <tr>
308        <th scope="col">getAction() value</th>
309        <th scope="col">Meaning</th>
310    </tr>
311    <tr>
312        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
313        <td>
314            A View object's drag event listener receives this event action type just after the
315            application calls
316{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} and
317            gets a drag shadow.
318        </td>
319    </tr>
320    <tr>
321        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
322        <td>
323            A View object's drag event listener receives this event action type when the drag shadow
324            has just entered the bounding box of the View. This is the first event action type the
325            listener receives when the drag shadow enters the bounding box. If the listener wants to
326            continue receiving drag events for this operation, it must return boolean
327            <code>true</code> to the system.
328        </td>
329    </tr>
330    <tr>
331        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
332        <td>
333            A View object's drag event listener receives this event action type after it receives a
334            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event while the drag shadow is
335            still within the bounding box of the View.
336        </td>
337    </tr>
338    <tr>
339        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
340        <td>
341            A View object's drag event listener receives this event action type after it receives a
342            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} and at least one
343            {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event, and after the user has moved
344            the drag shadow outside the bounding box of the View.
345        </td>
346    </tr>
347    <tr>
348        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
349        <td>
350            A View object's drag event listener receives this event action type when the user
351            releases the drag shadow over the View object. This action type is only sent to a View
352            object's listener if the listener returned boolean <code>true</code> in response to the
353            {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event. This action type is not
354            sent if the user releases the drag shadow on a View whose listener is not registered,
355            or if the user releases the drag shadow on anything that is not part of the current
356            layout.
357            <p>
358                The listener is expected to return boolean <code>true</code> if it successfully
359                processes the drop. Otherwise, it should return <code>false</code>.
360            </p>
361        </td>
362    </tr>
363    <tr>
364        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
365        <td>
366            A View object's drag event listener receives this event action type
367            when the system is ending the drag operation. This action type is not necessarily
368            preceded by an {@link android.view.DragEvent#ACTION_DROP} event. If the system sent
369            a {@link android.view.DragEvent#ACTION_DROP}, receiving the
370            {@link android.view.DragEvent#ACTION_DRAG_ENDED} action type does not imply that the
371            drop operation succeeded. The listener must call
372            {@link android.view.DragEvent#getResult()} to get the value that was
373            returned in response to {@link android.view.DragEvent#ACTION_DROP}. If an
374            {@link android.view.DragEvent#ACTION_DROP} event was not sent, then
375            {@link android.view.DragEvent#getResult()} returns <code>false</code>.
376        </td>
377    </tr>
378</table>
379<p class="table-caption" id="table2">
380  <strong>Table 2.</strong> Valid DragEvent data by action type</p>
381<table>
382    <tr>
383        <th scope="col">{@link android.view.DragEvent#getAction()} value</th>
384        <th scope="col">{@link android.view.DragEvent#getClipDescription()} value</th>
385        <th scope="col">{@link android.view.DragEvent#getLocalState()} value</th>
386        <th scope="col">{@link android.view.DragEvent#getX()} value</th>
387        <th scope="col">{@link android.view.DragEvent#getY()} value</th>
388        <th scope="col">{@link android.view.DragEvent#getClipData()} value</th>
389        <th scope="col">{@link android.view.DragEvent#getResult()} value</th>
390    </tr>
391    <tr>
392        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
393        <td style="text-align: center;">X</td>
394        <td style="text-align: center;">X</td>
395        <td style="text-align: center;">X</td>
396        <td style="text-align: center;">&nbsp;</td>
397        <td style="text-align: center;">&nbsp;</td>
398        <td style="text-align: center;">&nbsp;</td>
399    </tr>
400    <tr>
401        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
402        <td style="text-align: center;">X</td>
403        <td style="text-align: center;">X</td>
404        <td style="text-align: center;">X</td>
405        <td style="text-align: center;">X</td>
406        <td style="text-align: center;">&nbsp;</td>
407        <td style="text-align: center;">&nbsp;</td>
408    </tr>
409    <tr>
410        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
411        <td style="text-align: center;">X</td>
412        <td style="text-align: center;">X</td>
413        <td style="text-align: center;">X</td>
414        <td style="text-align: center;">X</td>
415        <td style="text-align: center;">&nbsp;</td>
416        <td style="text-align: center;">&nbsp;</td>
417    </tr>
418    <tr>
419        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
420        <td style="text-align: center;">X</td>
421        <td style="text-align: center;">X</td>
422        <td style="text-align: center;">&nbsp;</td>
423        <td style="text-align: center;">&nbsp;</td>
424        <td style="text-align: center;">&nbsp;</td>
425        <td style="text-align: center;">&nbsp;</td>
426    </tr>
427    <tr>
428        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
429        <td style="text-align: center;">X</td>
430        <td style="text-align: center;">X</td>
431        <td style="text-align: center;">X</td>
432        <td style="text-align: center;">X</td>
433        <td style="text-align: center;">X</td>
434        <td style="text-align: center;">&nbsp;</td>
435    </tr>
436    <tr>
437        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
438        <td style="text-align: center;">X</td>
439        <td style="text-align: center;">X</td>
440        <td style="text-align: center;">&nbsp;</td>
441        <td style="text-align: center;">&nbsp;</td>
442        <td style="text-align: center;">&nbsp;</td>
443        <td style="text-align: center;">X</td>
444    </tr>
445</table>
446<p>
447    The {@link android.view.DragEvent#getAction()},
448    {@link android.view.DragEvent#describeContents()},
449    {@link android.view.DragEvent#writeToParcel(Parcel,int) writeToParcel()}, and
450    {@link android.view.DragEvent#toString()} methods always return valid data.
451</p>
452<p>
453    If a method does not contain valid data for a particular action type, it returns either
454    <code>null</code> or 0, depending on its result type.
455</p>
456<h3 id="AboutDragShadowBuilder">
457    The drag shadow
458</h3>
459<p>
460    During a drag and drop operation, the system displays a image that the user drags.
461    For data movement, this image represents the data being dragged. For other operations, the
462    image represents some aspect of the drag operation.
463</p>
464<p>
465    The image is called a drag shadow. You create it with methods you declare for a
466    {@link android.view.View.DragShadowBuilder} object, and then pass it to the system when you
467    start a drag using
468    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
469    As part of its response to
470    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
471    the system invokes the callback methods you've defined in
472    {@link android.view.View.DragShadowBuilder} to obtain a drag shadow.
473</p>
474<p>
475    The {@link android.view.View.DragShadowBuilder} class has two constructors:
476</p>
477    <dl>
478    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)}</dt>
479    <dd>
480        This constructor accepts any of your application's
481        {@link android.view.View} objects. The constructor stores the View object
482        in the {@link android.view.View.DragShadowBuilder} object, so during
483        the callback you can access it as you construct your drag shadow.
484        It doesn't have to be associated with the View (if any) that the user
485        selected to start the drag operation.
486        <p>
487            If you use this constructor, you don't have to extend
488            {@link android.view.View.DragShadowBuilder} or override its methods. By default,
489            you will get a drag shadow that has the same appearance as the View you pass as an
490            argument, centered under the location where the user is touching the screen.
491        </p>
492    </dd>
493    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder()}</dt>
494    <dd>
495        If you use this constructor, no View object is available in the
496        {@link android.view.View.DragShadowBuilder} object (the field is set to <code>null</code>).
497        If you use this constructor, and you don't extend
498        {@link android.view.View.DragShadowBuilder} or override its methods,
499        you will get an invisible drag shadow.
500        The system does <em>not</em> give an error.
501    </dd>
502</dl>
503<p>
504    The {@link android.view.View.DragShadowBuilder} class has two methods:
505</p>
506<dl>
507    <dt>
508{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
509    </dt>
510    <dd>
511        The system calls this method immediately after you call
512{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}. Use it
513        to send to the system the dimensions and touch point of the drag shadow. The method has two
514        arguments:
515        <dl>
516            <dt><em>dimensions</em></dt>
517            <dd>
518                A {@link android.graphics.Point} object. The drag shadow width goes in
519                {@link android.graphics.Point#x} and its height goes in
520                {@link android.graphics.Point#y}.
521            </dd>
522            <dt><em>touch_point</em></dt>
523            <dd>
524                A {@link android.graphics.Point} object. The touch point is the location within the
525                drag shadow that should be under the user's finger during the drag. Its X
526                position goes in {@link android.graphics.Point#x} and its Y position goes in
527                {@link android.graphics.Point#y}
528            </dd>
529        </dl>
530    </dd>
531    <dt>
532       {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()}
533    </dt>
534    <dd>
535        Immediately after the call to
536{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
537        the system calls
538        {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()} to get the
539        drag shadow itself. The method has a single argument, a {@link android.graphics.Canvas}
540        object that the system constructs from the parameters you provide in
541{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
542        Use it to draw the drag shadow in the provided {@link android.graphics.Canvas} object.
543    </dd>
544</dl>
545<p>
546    To improve performance, you should keep the size of the drag shadow small. For a single item,
547    you may want to use a icon. For a multiple selection, you may want to use icons in a stack
548    rather than full images spread out over the screen.
549</p>
550<h2 id="DesignDragOperation">Designing a Drag and Drop Operation</h2>
551<p>
552    This section shows step-by-step how to start a drag, how to respond to events during
553    the drag, how respond to a drop event, and how to end the drag and drop operation.
554</p>
555<h3 id="StartDrag">Starting a drag</h3>
556<p>
557    The user starts a drag with a drag gesture, usually a long press, on a View object.
558    In response, you should do the following:
559</p>
560<ol>
561     <li>
562        As necessary, create a {@link android.content.ClipData} and
563        {@link android.content.ClipData.Item} for the data being moved. As part of the
564        ClipData object, supply metadata that is stored in a {@link android.content.ClipDescription}
565        object within the ClipData. For a drag and drop operation that does not represent data
566        movement, you may want to use <code>null</code> instead of an actual object.
567        <p>
568            For example, this code snippet shows how to respond to a long press on a ImageView
569            by creating a ClipData object that contains the tag or label of an
570            ImageView. Following this snippet, the next snippet shows how to override the methods in
571            {@link android.view.View.DragShadowBuilder}:
572        </p>
573<pre>
574// Create a string for the ImageView label
575private static final String IMAGEVIEW_TAG = &quot;icon bitmap&quot;
576
577// Creates a new ImageView
578ImageView imageView = new ImageView(this);
579
580// Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
581imageView.setImageBitmap(mIconBitmap);
582
583// Sets the tag
584imageView.setTag(IMAGEVIEW_TAG);
585
586    ...
587
588// Sets a long click listener for the ImageView using an anonymous listener object that
589// implements the OnLongClickListener interface
590imageView.setOnLongClickListener(new View.OnLongClickListener() {
591
592    // Defines the one method for the interface, which is called when the View is long-clicked
593    public boolean onLongClick(View v) {
594
595    // Create a new ClipData.
596    // This is done in two steps to provide clarity. The convenience method
597    // ClipData.newPlainText() can create a plain text ClipData in one step.
598
599    // Create a new ClipData.Item from the ImageView object's tag
600    ClipData.Item item = new ClipData.Item(v.getTag());
601
602    // Create a new ClipData using the tag as a label, the plain text MIME type, and
603    // the already-created item. This will create a new ClipDescription object within the
604    // ClipData, and set its MIME type entry to &quot;text/plain&quot;
605    ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
606
607    // Instantiates the drag shadow builder.
608    View.DrawShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
609
610    // Starts the drag
611
612            v.startDrag(dragData,  // the data to be dragged
613                        myShadow,  // the drag shadow builder
614                        null,      // no need to use local data
615                        0          // flags (not currently used, set to 0)
616            );
617
618    }
619}
620</pre>
621    </li>
622    <li>
623        The following code snippet defines {@code myDragShadowBuilder}
624        It creates a drag shadow for dragging a TextView as a small gray rectangle:
625<pre>
626    private static class MyDragShadowBuilder extends View.DragShadowBuilder {
627
628    // The drag shadow image, defined as a drawable thing
629    private static Drawable shadow;
630
631        // Defines the constructor for myDragShadowBuilder
632        public MyDragShadowBuilder(View v) {
633
634            // Stores the View parameter passed to myDragShadowBuilder.
635            super(v);
636
637            // Creates a draggable image that will fill the Canvas provided by the system.
638            shadow = new ColorDrawable(Color.LTGRAY);
639        }
640
641        // Defines a callback that sends the drag shadow dimensions and touch point back to the
642        // system.
643        &#64;Override
644        public void onProvideShadowMetrics (Point size, Point touch)
645            // Defines local variables
646            private int width, height;
647
648            // Sets the width of the shadow to half the width of the original View
649            width = getView().getWidth() / 2;
650
651            // Sets the height of the shadow to half the height of the original View
652            height = getView().getHeight() / 2;
653
654            // The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
655            // Canvas that the system will provide. As a result, the drag shadow will fill the
656            // Canvas.
657            shadow.setBounds(0, 0, width, height);
658
659            // Sets the size parameter's width and height values. These get back to the system
660            // through the size parameter.
661            size.set(width, height);
662
663            // Sets the touch point's position to be in the middle of the drag shadow
664            touch.set(width / 2, height / 2);
665        }
666
667        // Defines a callback that draws the drag shadow in a Canvas that the system constructs
668        // from the dimensions passed in onProvideShadowMetrics().
669        &#64;Override
670        public void onDrawShadow(Canvas canvas) {
671
672            // Draws the ColorDrawable in the Canvas passed in from the system.
673            shadow.draw(canvas);
674        }
675    }
676</pre>
677        <p class="note">
678            <strong>Note:</strong> Remember that you don't have to extend
679            {@link android.view.View.DragShadowBuilder}. The constructor
680            {@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)} creates a
681            default drag shadow that's the same size as the View argument passed to it, with the
682            touch point centered in the drag shadow.
683        </p>
684    </li>
685</ol>
686<h3 id="HandleStart">Responding to a drag start</h3>
687<p>
688    During the drag operation, the system dispatches drag events to the drag event listeners
689    of the View objects in the current layout. The listeners should react
690    by calling {@link android.view.DragEvent#getAction()} to get the action type.
691    At the start of a drag, this methods returns {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
692</p>
693<p>
694    In response to an event with the action type {@link android.view.DragEvent#ACTION_DRAG_STARTED},
695    a listener should do the following:
696</p>
697<ol>
698    <li>
699        Call {@link android.view.DragEvent#getClipDescription()} to get the
700        {@link android.content.ClipDescription}. Use the MIME type methods in
701        {@link android.content.ClipDescription} to see if the listener can accept the data being
702        dragged.
703        <p>
704            If the drag and drop operation does not represent data movement, this may not be
705            necessary.
706        </p>
707    </li>
708    <li>
709        If the listener can accept a drop, it should return <code>true</code>. This tells
710        the system to continue to send drag events to the listener.
711        If it can't accept a drop, it should return <code>false</code>, and the system
712        will stop sending drag events until it sends out
713        {@link android.view.DragEvent#ACTION_DRAG_ENDED}.
714    </li>
715</ol>
716<p>
717    Note that for an {@link android.view.DragEvent#ACTION_DRAG_STARTED} event, these
718    the following {@link android.view.DragEvent} methods are not valid:
719    {@link android.view.DragEvent#getClipData()}, {@link android.view.DragEvent#getX()},
720    {@link android.view.DragEvent#getY()}, and {@link android.view.DragEvent#getResult()}.
721</p>
722<h3 id="HandleDuring">Handling events during the drag</h3>
723<p>
724    During the drag, listeners that returned <code>true</code> in response to
725    the {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event continue to receive drag
726    events. The types of drag events a listener receives during the drag depend on the location of
727    the drag shadow and the visibility of the listener's View.
728</p>
729<p>
730    During the drag, listeners primarily use drag events to decide if they should change the
731    appearance of their View.
732</p>
733<p>
734    During the drag, {@link android.view.DragEvent#getAction()} returns one of three
735    values:
736</p>
737<ul>
738    <li>
739        {@link android.view.DragEvent#ACTION_DRAG_ENTERED}:
740        The listener receives this when the touch point
741        (the point on the screen underneath the user's finger) has entered the bounding box of the
742        listener's View.
743    </li>
744    <li>
745        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}: Once the listener receives an
746        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and before it receives an
747        A{@link android.view.DragEvent#ACTION_DRAG_EXITED} event, it receives a new
748        {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event every time the touch point moves.
749        The {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()} methods
750        return the the X and Y coordinates of the touch point.
751    </li>
752    <li>
753        {@link android.view.DragEvent#ACTION_DRAG_EXITED}:  This event is sent to a listener that
754        previously received {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, after
755        the drag shadow is no longer within the bounding box of the listener's View.
756    </li>
757</ul>
758<p>
759    The listener does not need to react to any of these action types. If the listener returns a
760    value to the system, it is ignored. Here are some guidelines for responding to each of
761    these action types:
762</p>
763<ul>
764    <li>
765        In response to {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
766        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}, the listener can change the appearance
767        of the View to indicate that it is about to receive a drop.
768    </li>
769    <li>
770        An event with the action type {@link android.view.DragEvent#ACTION_DRAG_LOCATION} contains
771        valid data for {@link android.view.DragEvent#getX()} and
772        {@link android.view.DragEvent#getY()}, corresponding to the location of the touch point.
773        The listener may want to use this information to alter the appearance of that part of the
774        View that is at the touch point. The listener can also use this information
775        to determine the exact position where the user is going to drop the drag shadow.
776    </li>
777    <li>
778        In response to {@link android.view.DragEvent#ACTION_DRAG_EXITED}, the listener should reset
779        any appearance changes it applied in response to
780        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
781        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}. This indicates to the user that
782        the View is no longer an imminent drop target.
783    </li>
784</ul>
785<h3 id="HandleDrop">Responding to a drop</h3>
786<p>
787    When the user releases the drag shadow on a View in the application, and that View previously
788    reported that it could accept the content being dragged, the system dispatches a drag event
789    to that View with the action type {@link android.view.DragEvent#ACTION_DROP}. The listener
790    should do the following:
791</p>
792<ol>
793    <li>
794        Call {@link android.view.DragEvent#getClipData()} to get the
795        {@link android.content.ClipData} object that was originally supplied in the call
796        to
797{@link android.view.View#startDrag(ClipData, View.DragShadowBuilder, Object, int) startDrag()}
798        and store it. If the drag and drop operation does not represent data movement,
799        this may not be necessary.
800    </li>
801    <li>
802        Return boolean <code>true</code> to indicate that the drop was processed successfully, or
803        boolean <code>false</code> if it was not. The returned value becomes the value returned by
804        {@link android.view.DragEvent#getResult()} for an
805        {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
806        <p>
807            Note that if the system does not send out an {@link android.view.DragEvent#ACTION_DROP}
808            event, the value of {@link android.view.DragEvent#getResult()} for an
809            {@link android.view.DragEvent#ACTION_DRAG_ENDED} event is <code>false</code>.
810        </p>
811    </li>
812</ol>
813<p>
814    For an {@link android.view.DragEvent#ACTION_DROP} event,
815    {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()}
816    return the X and Y position of the drag point at the moment of the drop, using the coordinate
817    system of the View that received the drop.
818</p>
819<p>
820    The system does allow the user to release the drag shadow on a View whose listener is not
821    receiving drag events. It will also allow the user to release the drag shadow
822    on empty regions of the application's UI, or on areas outside of your application.
823    In all of these cases, the system does not send an event with action type
824    {@link android.view.DragEvent#ACTION_DROP}, although it does send out an
825    {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
826</p>
827<h3 id="HandleEnd">Responding to a drag end</h3>
828<p>
829    Immediately after the user releases the drag shadow, the system sends a
830    drag event to all of the drag event listeners in your application, with an action type of
831    {@link android.view.DragEvent#ACTION_DRAG_ENDED}. This indicates that the drag operation is
832    over.
833</p>
834<p>
835    Each listener should do the following:
836</p>
837<ol>
838    <li>
839        If listener changed its View object's appearance during the operation, it should reset the
840        View to its default appearance. This is a visual indication to the user that the operation
841        is over.
842    </li>
843    <li>
844        The listener can optionally call {@link android.view.DragEvent#getResult()} to find out more
845        about the operation. If a listener returned <code>true</code> in response to an event of
846        action type {@link android.view.DragEvent#ACTION_DROP}, then
847        {@link android.view.DragEvent#getResult()} will return boolean <code>true</code>. In all
848        other cases, {@link android.view.DragEvent#getResult()} returns boolean <code>false</code>,
849        including any case in which the system did not send out a
850        {@link android.view.DragEvent#ACTION_DROP} event.
851    </li>
852    <li>
853        The listener should return boolean <code>true</code> to the system.
854    </li>
855</ol>
856<p>
857</p>
858<h3 id="RespondEventSample">Responding to drag events: an example</h3>
859<p>
860    All drag events are initially received by your drag event method or listener. The following
861    code snippet is a simple example of reacting to drag events in a listener:
862</p>
863<pre>
864// Creates a new drag event listener
865mDragListen = new myDragEventListener();
866
867View imageView = new ImageView(this);
868
869// Sets the drag event listener for the View
870imageView.setOnDragListener(mDragListen);
871
872...
873
874protected class myDragEventListener implements View.OnDragEventListener {
875
876    // This is the method that the system calls when it dispatches a drag event to the
877    // listener.
878    public boolean onDrag(View v, DragEvent event) {
879
880        // Defines a variable to store the action type for the incoming event
881        final int action = event.getAction();
882
883        // Handles each of the expected events
884        switch(action) {
885
886            case DragEvent.ACTION_DRAG_STARTED:
887
888                // Determines if this View can accept the dragged data
889                if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
890
891                    // As an example of what your application might do,
892                    // applies a blue color tint to the View to indicate that it can accept
893                    // data.
894                    v.setColorFilter(Color.BLUE);
895
896                    // Invalidate the view to force a redraw in the new tint
897                    v.invalidate();
898
899                    // returns true to indicate that the View can accept the dragged data.
900                    return(true);
901
902                    } else {
903
904                    // Returns false. During the current drag and drop operation, this View will
905                    // not receive events again until ACTION_DRAG_ENDED is sent.
906                    return(false);
907
908                    }
909                break;
910
911            case DragEvent.ACTION_DRAG_ENTERED: {
912
913                // Applies a green tint to the View. Return true; the return value is ignored.
914
915                v.setColorFilter(Color.GREEN);
916
917                // Invalidate the view to force a redraw in the new tint
918                v.invalidate();
919
920                return(true);
921
922                break;
923
924                case DragEvent.ACTION_DRAG_LOCATION:
925
926                // Ignore the event
927                    return(true);
928
929                break;
930
931                case DragEvent.ACTION_DRAG_EXITED:
932
933                    // Re-sets the color tint to blue. Returns true; the return value is ignored.
934                    v.setColorFilter(Color.BLUE);
935
936                    // Invalidate the view to force a redraw in the new tint
937                    v.invalidate();
938
939                    return(true);
940
941                break;
942
943                case DragEvent.ACTION_DROP:
944
945                    // Gets the item containing the dragged data
946                    ClipData.Item item = event.getClipData().getItemAt(0);
947
948                    // Gets the text data from the item.
949                    dragData = item.getText();
950
951                    // Displays a message containing the dragged data.
952                    Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);
953
954                    // Turns off any color tints
955                    v.clearColorFilter();
956
957                    // Invalidates the view to force a redraw
958                    v.invalidate();
959
960                    // Returns true. DragEvent.getResult() will return true.
961                    return(true);
962
963                break;
964
965                case DragEvent.ACTION_DRAG_ENDED:
966
967                    // Turns off any color tinting
968                    v.clearColorFilter();
969
970                    // Invalidates the view to force a redraw
971                    v.invalidate();
972
973                    // Does a getResult(), and displays what happened.
974                    if (event.getResult()) {
975                        Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);
976
977                    } else {
978                        Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);
979
980                    };
981
982                    // returns true; the value is ignored.
983                    return(true);
984
985                break;
986
987                // An unknown action type was received.
988                default:
989                    Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
990
991                break;
992        };
993    };
994};
995</pre>