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