OSDN Git Service

Doc Change: Topics for copy/paste/drag/drop
authorJoe Malin <jmalin@google.com>
Wed, 19 Jan 2011 22:33:23 +0000 (14:33 -0800)
committerJoe Malin <jmalin@google.com>
Mon, 14 Feb 2011 17:47:22 +0000 (09:47 -0800)
Change-Id: I755216fe9d2afca87a9adaeb99840142ff34a685

docs/html/guide/guide_toc.cs
docs/html/guide/topics/clipboard/copy-paste.jd [new file with mode: 0644]
docs/html/guide/topics/ui/drag-drop.jd [new file with mode: 0644]
docs/html/images/ui/clipboard/copy_paste_framework.png [new file with mode: 0755]

index c52fd6a..a2a2be9 100644 (file)
                 <span class="en">Creating Status Bar Notifications</span>
               </a></li>
             </ul>
-          </li><!-- end of notifying the user -->
+          </li>
+          <li>
+              <a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
+                  Dragging and Dropping
+              </a><span class="new">new!</span>
+          </li>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">
                 <span class="en">Applying Styles and Themes</span>
               </a></li>
               </a></li>
         </ul>
       </li>
+      <li>
+        <a href="<?cs var:toroot ?>guide/topics/clipboard/copy-paste.html">
+            <span class="en">Copying and Pasting</span>
+        </a>
+        <span class="new">new!</span>
+      </li>
       <li><a href="<?cs var:toroot ?>guide/topics/media/index.html">
             <span class="en">Audio and Video</span>
           </a></li>
       <li class="toggle-list">
         <div>
            <a href="<?cs var:toroot ?>guide/developing/devices/index.html">
-                    <span class="en">Managing Virtual Devices</span>
-                </a>
+                <span class="en">Creating and Managing Virtual Devices</span>
+            </a>
         </div>
         <ul>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds.html">
               <span class="en">With AVD Manager</span>
-                </a>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/devices/managing-avds-cmdline.html">
-              <span class="en">From the Command Line</span>
-                </a>
+              <span class="en">On the Command Line</span>
+            </a>
           </li>
           <li>
            <a href="<?cs var:toroot ?>guide/developing/devices/emulator.html">
-                    <span class="en">Using the Android Emulator</span>
-                </a>
+                <span class="en">Using the Android Emulator</span>
+            </a>
           </li>
         </ul>
       </li>
           <span class="en">Using Hardware Devices</span>
         </a>
       </li>
-      
+
       <li class="toggle-list">
         <div>
           <a href="<?cs var:toroot ?>guide/developing/projects/index.html">
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/projects/projects-cmdline.html">
-                   <span class="en">From the Command Line</span>
+                <span class="en">On the Command Line</span>
             </a>
           </li>
         </ul>
         <ul>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects.html">
-                   <span class="en">From Eclipse with ADT</span>
+                <span class="en">In Eclipse with ADT</span>
             </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-projects-cmdline.html">
-                   <span class="en">From Other IDEs</span>
+                <span class="en">In Other IDEs</span>
             </a>
           </li>
           <li>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-log.html">
-                   <span class="en">Reading and Writing Logs</span>
+                <span class="en">Reading and Writing Log Messages</span>
             </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-ui.html">
-                   <span class="en">Debugging and Profiling UIs</span>
-               </a>
+                <span class="en">Debugging and Profiling UIs</span>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-tracing.html">
-                   <span class="en">Profiling with Traceview and dmtracedump</span>
-               </a>
+                <span class="en">Profiling with Traceview and dmtracedump</span>
+            </a>
           </li>
           <li>
             <a href="<?cs var:toroot ?>guide/developing/debugging/debugging-devtools.html">
-                   <span class="en">Using the Dev Tools App</span>
-               </a>
+                <span class="en">Using the Dev Tools App</span>
+            </a>
           </li>
         </ul>
       </li>
diff --git a/docs/html/guide/topics/clipboard/copy-paste.jd b/docs/html/guide/topics/clipboard/copy-paste.jd
new file mode 100644 (file)
index 0000000..9a50a35
--- /dev/null
@@ -0,0 +1,1094 @@
+page.title=Copying and Pasting
+@jd:body
+<div id="qv-wrapper">
+    <div id="qv">
+        <h2>Quickview</h2>
+            <ul>
+                <li>
+                    A clipboard-based framework for copying and pasting data.
+                </li>
+                <li>
+                    Supports both simple and complex data, including text strings, complex data
+                    structures, text and binary stream data, and application assets.
+                </li>
+                <li>
+                    Copies and pastes simple text directly to and from the clipboard.
+                </li>
+                <li>
+                    Copies and pastes complex data using a content provider.
+                </li>
+                <li>
+                    Requires API 11.
+                </li>
+            </ul>
+        <h2>In this document</h2>
+        <ol>
+            <li>
+                <a href="#Clipboard">The Clipboard Framework</a>
+            </li>
+            <li>
+                <a href="#ClipboardClasses">Clipboard Classes</a>
+                <ol>
+                    <li>
+                        <a href="#ClipboardManager">ClipboardManager</a>
+                    </li>
+                    <li>
+                        <a href="#ClipClasses">
+                            ClipData, ClipDescription, and ClipData.Item
+                        </a>
+                    </li>
+                    <li>
+                        <a href="#ClipDataMethods">ClipData convenience methods</a>
+                    </li>
+                    <li>
+                        <a href="#CoerceToText">Coercing the clipboard data to text</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#Copying">Copying to the Clipboard</a>
+            </li>
+            <li>
+                <a href="#Pasting">Pasting from the Clipboard</a>
+                <ol>
+                    <li>
+                        <a href="#PastePlainText">Pasting plain text</a>
+                    </li>
+                    <li>
+                        <a href="#PasteContentUri">Pasting data from a content URI</a>
+                    </li>
+                    <li>
+                        <a href="#PasteIntent">Pasting an Intent</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#Provider">Using Content Providers to Copy Complex Data</a>
+                <ol>
+                    <li>
+                        <a href="#Encoding">Encoding an identifier on the URI</a>
+                    </li>
+                    <li>
+                        <a href="#Records">Copying data structures</a>
+                    </li>
+                    <li>
+                        <a href="#Streams">Copying data streams</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#DataDesign">Designing Effective Copy/Paste Functionality</a>
+            </li>
+        </ol>
+        <h2>Key classes</h2>
+        <ol>
+            <li>
+                {@link android.content.ClipboardManager ClipboardManager}
+            </li>
+            <li>
+                {@link android.content.ClipData ClipData}
+            </li>
+            <li>
+                {@link android.content.ClipData.Item ClipData.Item}
+            </li>
+            <li>
+                {@link android.content.ClipDescription ClipDescription}
+            </li>
+            <li>
+                {@link android.net.Uri Uri}
+            </li>
+            <li>
+                {@link android.content.ContentProvider}
+            </li>
+            <li>
+                {@link android.content.Intent Intent}
+            </li>
+        </ol>
+        <h2>Related Samples</h2>
+        <ol>
+            <li>
+                <a href="{@docRoot}resources/samples/NotePad/index.html">
+                Note Pad sample application</a>
+            </li>
+        </ol>
+        <h2>See also</h2>
+        <ol>
+            <li>
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+            </li>
+        </ol>
+    </div>
+</div>
+<p>
+    Android provides a powerful clipboard-based framework for copying and pasting. It
+    supports both simple and complex data types, including text strings, complex data
+    structures, text and binary stream data, and even application assets. Simple text data is stored
+    directly in the clipboard, while complex data is stored as a reference that the pasting
+    application resolves with a content provider. Copying and pasting works both within an
+    application and between applications that implement the framework.
+</p>
+
+<p>
+    Since a part of the framework uses content providers, this topic assumes some
+    familiarity with the Android Content Provider API, which is described in the topic
+    <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+</p>
+<h2 id="Clipboard">The Clipboard Framework</h2>
+<p>
+    When you use the clipboard framework, you put data into a clip object, and then
+    put the clip object on the system-wide clipboard. The clip object can take one of three forms:
+</p>
+    <dl>
+        <dt>Text</dt>
+        <dd>
+            A text string. You put the string directly into the clip object, which you then put onto
+            the clipboard. To paste the string, you get the clip object from the clipboard and copy
+            the string to into your application's storage.
+        </dd>
+        <dt>URI</dt>
+        <dd>
+            A {@link android.net.Uri} object representing any form of URI. This is primarily for
+            copying complex data from a content provider. To copy data, you put a
+            {@link android.net.Uri} object into a clip object and put the clip object onto
+            the clipboard. To paste the data, you get the clip object, get the
+            {@link android.net.Uri} object, resolve it to a data source such as a content provider,
+            and copy the data from the source into your application's storage.
+        </dd>
+        <dt>Intent</dt>
+        <dd>
+            An {@link android.content.Intent}. This supports copying application shortcuts. To copy
+            data, you create an Intent, put it into a clip object, and put the clip object onto the
+            clipboard. To paste the data, you get the clip object and then copy the Intent object
+            into your application's memory area.
+        </dd>
+    </dl>
+<p>
+    The clipboard holds only one clip object at a time. When an application puts a clip object on
+    the clipboard, the previous clip object disappears.
+</p>
+<p>
+    If you want to allow users to paste data into your application, you don't have to handle all
+    types of data. You can examine the data on the clipboard before you give users the option to
+    paste it. Besides having a certain data form, the clip object also contains metadata that tells
+    you what MIME type or types are available. This metadata helps you decide if your application
+    can do something useful with the clipboard data. For example, if you have an application that
+    primarily handles text you may want to ignore clip objects that contain a URI or Intent.
+</p>
+<p>
+    You may also want to allow users to paste text regardless of the form of data on the
+    clipboard. To do this, you can force the clipboard data into a text representation, and then
+    paste this text. This is described in the section <a href="#CoerceToText">Coercing the
+    clipboard to text</a>.
+</p>
+<h2 id="ClipboardClasses">Clipboard Classes</h2>
+<p>
+    This section describes the classes used by the clipboard framework.
+</p>
+<h3 id="ClipboardManager">ClipboardManager</h3>
+<p>
+    In the Android system, the system clipboard is represented by the global
+    {@link android.content.ClipboardManager} class. You do not instantiate this
+    class directly; instead, you get a reference to it by invoking
+    {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}.
+</p>
+<h3 id="ClipClasses">ClipData, ClipData.Item, and ClipDescription</h3>
+<p>
+    To add data to the clipboard, you create a {@link android.content.ClipData} object that
+    contains both a description of the data and the data itself. The clipboard holds only one
+    {@link android.content.ClipData} at a time. A {@link android.content.ClipData} contains a
+    {@link android.content.ClipDescription} object and one or more
+    {@link android.content.ClipData.Item} objects.
+</p>
+<p>
+    A {@link android.content.ClipDescription} object contains metadata about the clip. In
+    particular, it contains an array of available MIME types for the clip's data. When you put a
+    clip on the clipboard, this array is available to pasting applications, which can examine it to
+    see if they can handle any of available the MIME types.
+</p>
+<p>
+    A {@link android.content.ClipData.Item} object contains the text, URI, or Intent data:
+</p>
+<dl>
+    <dt>Text</dt>
+    <dd>
+        A {@link java.lang.CharSequence}.
+    </dd>
+    <dt>URI</dt>
+    <dd>
+        A {@link android.net.Uri}. This usually contains a content provider URI, although any
+        URI is allowed. The application that provides the data puts the URI on the clipboard.
+        Applications that want to paste the data get the URI from the clipboard and use it to
+        access the content provider (or other data source) and retrieve the data.
+    </dd>
+    <dt>Intent</dt>
+    <dd>
+        An {@link android.content.Intent}. This data type allows you to copy an application shortcut
+        to the clipboard. Users can then paste the shortcut into their applications for later use.
+    </dd>
+</dl>
+<p>
+    You can add more than one {@link android.content.ClipData.Item} object to a clip. This allows
+    users to copy and paste multiple selections as a single clip. For example, if you have a list
+    widget that allows the user to select more than one item at a time, you can copy all the items
+    to the clipboard at once. To do this, you create a separate
+    {@link android.content.ClipData.Item} for each list item, and then you add the
+    {@link android.content.ClipData.Item} objects to the {@link android.content.ClipData} object.
+</p>
+<h3 id="ClipDataMethods">ClipData convenience methods</h3>
+<p>
+    The {@link android.content.ClipData} class provides static convenience methods for creating
+    a {@link android.content.ClipData} object with a single {@link android.content.ClipData.Item}
+    object and a simple {@link android.content.ClipDescription} object:
+</p>
+<dl>
+    <dt>
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText(label, text)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains a text string. The
+        {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        The single MIME type in {@link android.content.ClipDescription} is
+        {@link android.content.ClipDescription#MIMETYPE_TEXT_PLAIN}.
+        <p>
+            Use
+{@link android.content.ClipData#newPlainText(CharSequence,CharSequence) newPlainText()}
+            to create a clip from a text string.
+    </dd>
+    <dt>
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri(resolver, label, URI)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains a URI. The
+        {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        If the URI is a content URI ({@link android.net.Uri#getScheme() Uri.getScheme()} returns
+        <code>content:</code>), the method uses the {@link android.content.ContentResolver} object
+        provided in <code>resolver</code> to retrieve the available MIME types from the
+        content provider and store them in {@link android.content.ClipDescription}. For a URI that
+        is not a <code>content:</code> URI, the method sets the MIME type to
+        {@link android.content.ClipDescription#MIMETYPE_TEXT_URILIST}.
+        <p>
+            Use
+{@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()}
+            to create a clip from a URI, particularly a <code>content:</code> URI.
+        </p>
+    </dd>
+    <dt>
+        {@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent(label, intent)}
+    </dt>
+    <dd>
+        Returns a {@link android.content.ClipData} object whose single
+        {@link android.content.ClipData.Item} object contains an {@link android.content.Intent}.
+        The {@link android.content.ClipDescription} object's label is set to <code>label</code>.
+        The MIME type is set to {@link android.content.ClipDescription#MIMETYPE_TEXT_INTENT}.
+        <p>
+            Use
+{@link android.content.ClipData#newIntent(CharSequence, Intent) newIntent()}
+            to create a clip from an Intent object.
+    </dd>
+</dl>
+<h3 id="CoerceToText">Coercing the clipboard data to text</h3>
+<p>
+    Even if your application only handles text, you can copy non-text data from the
+    clipboard by converting it with the method
+    {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}.
+</p>
+<p>
+    This method converts the data in {@link android.content.ClipData.Item} to text and
+    returns a {@link java.lang.CharSequence}. The value that
+    {@link android.content.ClipData.Item#coerceToText(Context) ClipData.Item.coerceToText()}
+    returns is based on the form of data in {@link android.content.ClipData.Item}:
+</p>
+<dl>
+    <dt><em>Text</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is text
+        ({@link android.content.ClipData.Item#getText()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns the
+        text.
+    </dd>
+    <dt><em>URI</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is a URI
+        ({@link android.content.ClipData.Item#getUri()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} tries to use
+        it as a content URI:
+    <ul>
+        <li>
+                If the URI is a content URI and the provider can return a text stream,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a text stream.
+            </li>
+            <li>
+                If the URI is a content URI but the provider does not offer a text stream,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a representation of the URI. The representation is the same as that returned by
+                {@link android.net.Uri#toString() Uri.toString()}.
+            </li>
+            <li>
+                If the URI is not a content URI,
+                {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} returns
+                a representation of the URI. The representation is the same as that returned by
+                {@link android.net.Uri#toString() Uri.toString()}.
+            </li>
+        </ul>
+    </dd>
+    <dt><em>Intent</em></dt>
+    <dd>
+        If {@link android.content.ClipData.Item} is an Intent
+        ({@link android.content.ClipData.Item#getIntent()} is not null),
+        {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} converts it to
+        an Intent URI and returns it. The representation is the same as that returned by
+        {@link android.content.Intent#toUri(int) Intent.toUri(URI_INTENT_SCHEME)}.
+    </dd>
+</dl>
+<p>
+    The clipboard framework is summarized in Figure 1. To copy data, an application puts a
+    {@link android.content.ClipData} object on the {@link android.content.ClipboardManager} global
+    clipboard. The {@link android.content.ClipData} contains one or more
+    {@link android.content.ClipData.Item} objects and one
+    {@link android.content.ClipDescription} object. To paste data, an application gets the
+    {@link android.content.ClipData}, gets its MIME type from the
+    {@link android.content.ClipDescription}, and gets the data either from
+    the {@link android.content.ClipData.Item} or from the content provider referred to by
+    {@link android.content.ClipData.Item}.
+</p>
+    <a name="framework"></a>
+    <img
+        src="{@docRoot}images/ui/clipboard/copy_paste_framework.png"
+        alt="A block diagram of the copy and paste framework" height="400px" id="figure1" />
+<p class="img-caption">
+    <strong>Figure 1.</strong> The Android clipboard framework
+</p>
+<h2 id="Copying">Copying to the Clipboard</h2>
+<p>
+    As described previously, to copy data to the clipboard you get a handle to the global
+    {@link android.content.ClipboardManager} object, create a {@link android.content.ClipData}
+    object, add a {@link android.content.ClipDescription} and one or more
+    {@link android.content.ClipData.Item} objects to it, and add the finished
+    {@link android.content.ClipData} object to the {@link android.content.ClipboardManager} object.
+    This is described in detail in the following procedure:
+</p>
+<ol>
+    <li>
+        If you are copying data using a content URI, set up a content
+        provider.
+        <p>
+            The <a href="{@docRoot}resources/samples/NotePad/index.html">
+            Note Pad</a> sample application is an example of using a content provider for
+            copying and pasting. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePadProvider.html">
+            NotePadProvider</a> class implements the content provider. The
+<a href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NotePad.html">
+            NotePad</a> class defines a contract between the provider and other applications,
+            including the supported MIME types.
+        </p>
+    </li>
+    <li>
+        Get the system clipboard:
+<pre>
+
+...
+
+// if the user selects copy
+case R.id.menu_copy:
+
+// Gets a handle to the clipboard service.
+ClipboardManager clipboard = (ClipboardManager)
+        getSystemService(Context.CLIPBOARD_SERVICE);
+</pre>
+    </li>
+    <li>
+        <p>
+            Copy the data to a new {@link android.content.ClipData} object:
+        </p>
+        <ul>
+            <li>
+                <h4>For text</h4>
+<pre>
+// Creates a new text clip to put on the clipboard
+ClipData clip = ClipData.newPlainText(&quot;simple text&quot;,&quot;Hello, World!&quot;);
+</pre>
+            </li>
+            <li>
+                <h4>For a URI</h4>
+                <p>
+                    This snippet constructs a URI by encoding a record ID onto the content URI
+                    for the provider. This technique is covered in more detail
+                    in the section <a href="#Encoding">Encoding an identifier on the URI</a>:
+                </p>
+<pre>
+// Creates a Uri based on a base Uri and a record ID based on the contact's last name
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares the Uri to paste to the clipboard
+Uri copyUri = Uri.parse(CONTACTS + COPY_PATH + &quot;/&quot; + lastName);
+
+...
+
+// Creates a new URI clip object. The system uses the anonymous getContentResolver() object to
+// get MIME types from provider. The clip object's label is &quot;URI&quot;, and its data is
+// the Uri previously created.
+ClipData clip = ClipData.newUri(getContentResolver(),&quot;URI&quot;,copyUri);
+</pre>
+            </li>
+            <li>
+                <h4>For an Intent</h4>
+                <p>
+                    This snippet constructs an Intent for an application
+                    and then puts it in the clip object:
+                </p>
+<pre>
+// Creates the Intent
+Intent appIntent = new Intent(this, com.example.demo.myapplication.class);
+
+...
+
+// Creates a clip object with the Intent in it. Its label is &quot;Intent&quot; and its data is
+// the Intent object created previously
+ClipData clip = ClipData.newIntent(&quot;Intent&quot;,appIntent);
+</pre>
+            </li>
+        </ul>
+    </li>
+    <li>
+        Put the new clip object on the clipboard:
+<pre>
+// Set the clipboard's primary clip.
+clipboard.setPrimaryClip(clip);
+</pre>
+    </li>
+</ol>
+<h2 id="Pasting">Pasting from the Clipboard</h2>
+<p>
+    As described previously, you paste data from the clipboard by getting the global clipboard
+    object, getting the clip object, looking at its data, and if possible copying the data from
+    the clip object to your own storage. This section describes in detail how to do this for
+    the three forms of clipboard data.
+</p>
+<h3 id="PastePlainText">Pasting plain text</h3>
+<p>
+    To paste plain text, first get the global clipboard and verify that it can return plain text.
+    Then get the clip object and copy its text to your own storage using
+    {@link android.content.ClipData.Item#getText()}, as described in the following procedure:
+</p>
+<ol>
+    <li>
+        Get the global {@link android.content.ClipboardManager} object using
+ {@link android.content.Context#getSystemService(String) getSystemService(CLIPBOARD_SERVICE)}. Also
+        declare a global variable to contain the pasted text:
+<pre>
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+String pasteData = &quot;&quot;;
+
+</pre>
+    </li>
+    <li>
+        Next, determine if you should enable or disable the &quot;paste&quot; option in the
+        current Activity. You should verify that the clipboard contains a clip and that you
+        can handle the type of data represented by the clip:
+<pre>
+// Gets the ID of the &quot;paste&quot; menu item
+MenuItem mPasteItem = menu.findItem(R.id.menu_paste);
+
+// If the clipboard doesn't contain data, disable the paste menu item.
+// If it does contain data, decide if you can handle the data.
+if (!(clipboard.hasPrimaryClip())) {
+
+    mPasteItem.setEnabled(false);
+
+    } else if (!(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) {
+
+        // This disables the paste menu item, since the clipboard has data but it is not plain text
+        mPasteItem.setEnabled(false);
+    } else {
+
+        // This enables the paste menu item, since the clipboard contains plain text.
+        mPasteItem.setEnabled(true);
+    }
+}
+</pre>
+    </li>
+    <li>
+        Copy the data from the clipboard. This point in the program is only reachable if the
+        &quot;paste&quot; menu item is enabled, so you can assume that the clipboard contains
+        plain text. You do not yet know if it contains a text string or a URI that points to plain
+        text. The following snippet tests this, but it only shows the code for handling plain text:
+<pre>
+// Responds to the user selecting &quot;paste&quot;
+case R.id.menu_paste:
+
+// Examines the item on the clipboard. If getText() does not return null, the clip item contains the
+// text. Assumes that this application can only handle one item at a time.
+ ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0);
+
+// Gets the clipboard as text.
+pasteData = item.getText();
+
+// If the string contains data, then the paste operation is done
+if (pasteData != null) {
+    return;
+
+// The clipboard does not contain text. If it contains a URI, attempts to get data from it
+} else {
+    Uri pasteUri = item.getUri();
+
+    // If the URI contains something, try to get text from it
+    if (pasteUri != null) {
+
+        // calls a routine to resolve the URI and get data from it. This routine is not
+        // presented here.
+        pasteData = resolveUri(Uri);
+        return;
+    } else {
+
+    // Something is wrong. The MIME type was plain text, but the clipboard does not contain either
+    // text or a Uri. Report an error.
+    Log.e(&quot;Clipboard contains an invalid data type&quot;);
+    return;
+    }
+}
+</pre>
+    </li>
+</ol>
+<h3 id="PasteContentUri">Pasting data from a content URI</h3>
+<p>
+    If the {@link android.content.ClipData.Item} object contains a content URI and you
+    have determined that you can handle one of its MIME types, create a
+    {@link android.content.ContentResolver} and then call the appropriate content provider
+    method to retrieve the data.
+</p>
+<p>
+    The following procedure describes how to get data from a content provider based on a
+    content URI on the clipboard. It checks that a MIME type that the application can use
+    is available from the provider:
+</p>
+<ol>
+    <li>
+        Declare a global variable to contain the MIME type:
+<pre>
+// Declares a MIME type constant to match against the MIME types offered by the provider
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+    </li>
+    <li>
+        Get the global clipboard. Also get a content resolver so you can access the content
+        provider:
+<pre>
+// Gets a handle to the Clipboard Manager
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+// Gets a content resolver instance
+ContentResolver cr = getContentResolver();
+</pre>
+    </li>
+    <li>
+        Get the primary clip from the clipboard, and get its contents as a URI:
+<pre>
+// Gets the clipboard data from the clipboard
+ClipData clip = clipboard.getPrimaryClip();
+
+if (clip != null) {
+
+    // Gets the first item from the clipboard data
+    ClipData.Item item = clip.getItemAt(0);
+
+    // Tries to get the item's contents as a URI
+    Uri pasteUri = item.getUri();
+</pre>
+    </li>
+    <li>
+        Test to see if the URI is a content URI by calling
+        {@link android.content.ContentResolver#getType(Uri) getType(Uri)}. This method returns
+        null if <code>Uri</code> does not point to a valid content provider:
+<pre>
+    // If the clipboard contains a URI reference
+    if (pasteUri != null) {
+
+        // Is this a content URI?
+        String uriMimeType = cr.getType(pasteUri);
+</pre>
+    </li>
+    <li>
+        Test to see if the content provider supports a MIME type that the current application
+        understands. If it does, call
+        {@link android.content.ContentResolver#query(Uri, String[], String, String[], String)
+        ContentResolver.query()} to get the data. The return value is a
+        {@link android.database.Cursor}:
+<pre>
+        // If the return value is not null, the Uri is a content Uri
+        if (uriMimeType != null) {
+
+            // Does the content provider offer a MIME type that the current application can use?
+            if (uriMimeType.equals(MIME_TYPE_CONTACT)) {
+
+                // Get the data from the content provider.
+                Cursor pasteCursor = cr.query(uri, null, null, null, null);
+
+                // If the Cursor contains data, move to the first record
+                if (pasteCursor != null) {
+                    if (pasteCursor.moveToFirst()) {
+
+                    // get the data from the Cursor here. The code will vary according to the
+                    // format of the data model.
+                    }
+                }
+
+                // close the Cursor
+                pasteCursor.close();
+             }
+         }
+     }
+}
+</pre>
+    </li>
+</ol>
+<h3 id="PasteIntent">Pasting an Intent</h3>
+<p>
+    To paste an Intent, first get the global clipboard. Examine the
+    {@link android.content.ClipData.Item} object to see if it contains an Intent. Then call
+    {@link android.content.ClipData.Item#getIntent()} to copy the Intent to your own storage.
+    The following snippet demonstrates this:
+</p>
+<pre>
+// Gets a handle to the Clipboard Manager
+ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
+
+// Checks to see if the clip item contains an Intent, by testing to see if getIntent() returns null
+Intent pasteIntent = clipboard.getPrimaryClip().getItemAt(0).getIntent();
+
+if (pasteIntent != null) {
+
+    // handle the Intent
+
+} else {
+
+    // ignore the clipboard, or issue an error if your application was expecting an Intent to be
+    // on the clipboard
+}
+</pre>
+<h2 id="Provider">Using Content Providers to Copy Complex Data</h2>
+<p>
+    Content providers support copying complex data such as database records or file streams.
+    To copy the data, you put a content URI on the clipboard. Pasting applications then get this
+    URI from the clipboard and use it to retrieve database data or file stream descriptors.
+</p>
+<p>
+    Since the pasting application only has the content URI for your data, it needs to know which
+    piece of data to retrieve. You can provide this information by encoding an identifier for the
+    data on the URI itself, or you can provide a unique URI that will return the data you want to
+    copy. Which technique you choose depends on the organization of your data.
+</p>
+<p>
+    The following sections describe how to set up URIs, how to provide complex data, and how to
+    provide file streams. The descriptions assume that you are familiar with the general principles
+    of content provider design.
+</p>
+<h3 id="Encoding">Encoding an identifier on the URI</h3>
+<p>
+    A useful technique for copying data to the clipboard with a URI is to encode an identifier for
+    the data on the URI itself. Your content provider can then get the identifier from the URI and
+    use it to retrieve the data. The pasting application doesn't have to know that the identifier
+    exists; all it has to do is get your &quot;reference&quot; (the URI plus the identifier) from
+    the clipboard, give it your content provider, and get back the data.
+</p>
+<p>
+    You usually encode an identifier onto a content URI by concatenating it to the end of the URI.
+    For example, suppose you define your provider URI as the following string:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;
+</pre>
+<p>
+   If you want to encode a name onto this URI, you would use the following snippet:
+</p>
+<pre>
+String uriString = &quot;content:&#47;&#47;com.example.contacts&quot; + &quot;/&quot; + &quot;Smith&quot;
+
+// uriString now contains content://com.example.contacts/Smith.
+
+// Generates a uri object from the string representation
+Uri copyUri = Uri.parse(uriString);
+</pre>
+<p>
+    If you are already using a content provider, you may want to add a new URI path that indicates
+    the URI is for copying. For example, suppose you already have the following URI paths:
+</p>
+<pre>
+&quot;content://com.example.contacts&quot;/people
+&quot;content://com.example.contacts&quot;/people/detail
+&quot;content://com.example.contacts&quot;/people/images
+</pre>
+<p>
+   You could add another path that is specific to copy URIs:
+</p>
+<pre>
+&quot;content://com.example.contacts/copying&quot;
+</pre>
+<p>
+    You could then detect a &quot;copy&quot; URI by pattern-matching and handle it with code that
+    is specific for copying and pasting.
+</p>
+<p>
+    You normally use the encoding technique if you're already using a content provider, internal
+    database, or internal table to organize your data. In these cases, you have multiple pieces of
+    data you want to copy, and presumably a unique identifier for each piece. In response to a
+    query from the pasting application, you can look up the data by its identifier and return it.
+</p>
+<p>
+    If you don't have multiple pieces of data, then you probably don't need to encode an identifier.
+    You can simply use a URI that is unique to your provider. In response to a query, your provider
+    would return the data it currently contains.
+</p>
+<p>
+    Getting a single record by ID is used in the
+    <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample application to
+    open a note from the notes list. The sample uses the <code>_id</code> field from an SQL
+    database, but you can have any numeric or character identifier you want.
+</p>
+<h3 id="Records">Copying data structures</h3>
+<p>
+    You set up a content provider for copying and pasting complex data as a subclass of the
+    {@link android.content.ContentProvider} component. You should also encode the URI you put on
+    the clipboard so that it points to the exact record you want to provide. In addition, you
+    have to consider the existing state of your application:
+</p>
+<ul>
+    <li>
+        If you already have a content provider, you can add to its functionality. You may only
+        need to modify its
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+        method to handle URIs coming from applications that want to paste data. You will
+        probably want to modify the method to handle a &quot;copy&quot; URI pattern.
+    </li>
+    <li>
+        If your application maintains an internal database, you may
+        want to move this database into a content provider to facilitate copying from it.
+    </li>
+    <li>
+        If you are not currently using a database, you can implement a simple content provider
+        whose sole purpose is to offer data to applications that are pasting from the
+        clipboard.
+    </li>
+</ul>
+<p>
+In the content provider, you will want to override at least the following methods:
+</p>
+<dl>
+    <dt>
+{@link android.content.ContentResolver#query(Uri, String[], String, String[], String) query()}
+    </dt>
+    <dd>
+        Pasting applications will assume that they can get your data by using this method with
+        the URI you put on the clipboard. To support copying, you should have this method
+        detect URIs that contain a special &quot;copy&quot; path. Your application can then
+        create a &quot;copy&quot; URI to put on the clipboard, containing the copy path and
+        a pointer to the exact record you want to copy.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#getType(Uri) getType()}
+    </dt>
+    <dd>
+        This method should return the MIME type or types for the data you intend to copy. The method
+        {@link android.content.ClipData#newUri(ContentResolver, CharSequence, Uri) newUri()} calls
+        {@link android.content.ContentProvider#getType(Uri) getType()} in order to put the MIME
+        types into the new {@link android.content.ClipData} object.
+        <p>
+            MIME types for complex data are described in the topic
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.
+        </p>
+    </dd>
+</dl>
+<p>
+    Notice that you don't have to have any of the other content provider methods such as
+    {@link android.content.ContentProvider#insert(Uri, ContentValues) insert()} or
+    {@link android.content.ContentProvider#update(Uri, ContentValues, String, String[]) update()}.
+    A pasting application only needs to get your supported MIME types and copy data from your
+    provider. If you already have these methods, they won't interfere with copy operations.
+</p>
+<p>
+    The following snippets demonsrate how to set up your application to copy complex data:
+</p>
+<ol>
+    <li>
+        <p>
+            In the global constants for your application,
+            declare a base URI string and a path that identifies URI strings you are
+            using to copy data. Also declare a MIME type for the copied data:
+        </p>
+<pre>
+// Declares the base URI string
+private static final String CONTACTS = &quot;content:&#47;&#47;com.example.contacts&quot;;
+
+// Declares a path string for URIs that you use to copy data
+private static final String COPY_PATH = &quot;/copy&quot;;
+
+// Declares a MIME type for the copied data
+public static final String MIME_TYPE_CONTACT = &quot;vnd.android.cursor.item/vnd.example.contact&quot;
+</pre>
+    </li>
+    <li>
+        In the Activity from which users copy data,
+        set up the code to copy data to the clipboard. In response to a copy request, put
+        the URI on the clipboard:
+<pre>
+public class MyCopyActivity extends Activity {
+
+    ...
+
+// The user has selected a name and is requesting a copy.
+case R.id.menu_copy:
+
+    // Appends the last name to the base URI
+    // The name is stored in &quot;lastName&quot;
+    uriString = CONTACTS + COPY_PATH + &quot;/&quot; + lastName;
+
+    // Parses the string into a URI
+    Uri copyUri = Uri.parse(uriString);
+
+    // Gets a handle to the clipboard service.
+    ClipboardManager clipboard = (ClipboardManager)
+        getSystemService(Context.CLIPBOARD_SERVICE);
+
+    ClipData clip = ClipData.newUri(getContentResolver(), &quot;URI&quot;, copyUri);
+
+    // Set the clipboard's primary clip.
+    clipboard.setPrimaryClip(clip);
+</pre>
+    </li>
+
+    <li>
+    <p>
+        In the global scope of your content provider, create a URI matcher and add a URI
+        pattern that will match URIs you put on the clipboard:
+    </p>
+<pre>
+public class MyCopyProvider extends ContentProvider {
+
+    ...
+
+// A Uri Match object that simplifies matching content URIs to patterns.
+private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+// An integer to use in switching based on the incoming URI pattern
+private static final int GET_SINGLE_CONTACT = 0;
+
+...
+
+// Adds a matcher for the content URI. It matches
+// &quot;content://com.example.contacts/copy/*&quot;
+sUriMatcher.addURI(CONTACTS, "names/*", GET_SINGLE_CONTACT);
+</pre>
+    </li>
+    <li>
+    <p>
+        Set up the
+     {@link android.content.ContentProvider#query(Uri, String[], String, String[], String) query()}
+        method. This method can handle different URI patterns, depending on how you code it, but
+        only the pattern for the clipboard copying operation is shown:
+    </p>
+<pre>
+// Sets up your provider's query() method.
+public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+    String sortOrder) {
+
+    ...
+
+    // Switch based on the incoming content URI
+    switch (sUriMatcher.match(uri)) {
+
+    case GET_SINGLE_CONTACT:
+
+        // query and return the contact for the requested name. Here you would decode
+        // the incoming URI, query the data model based on the last name, and return the result
+        // as a Cursor.
+
+    ...
+
+}
+</pre>
+    </li>
+    <li>
+        <p>
+            Set up the {@link android.content.ContentProvider#getType(Uri) getType()} method to
+            return an appropriate MIME type for copied data:
+        </p>
+<pre>
+// Sets up your provider's getType() method.
+public String getType(Uri uri) {
+
+    ...
+
+    switch (sUriMatcher.match(uri)) {
+
+    case GET_SINGLE_CONTACT:
+
+            return (MIME_TYPE_CONTACT);
+</pre>
+    </li>
+</ol>
+<p>
+    The section <a href="#PasteContentUri">Pasting data from a content URI</a>
+    describes how to get a content URI from the clipboard and use it to get and paste data.
+</p>
+<h3 id="Streams">Copying data streams</h3>
+<p>
+    You can copy and paste large amounts of text and binary data as streams. The data can have
+    forms such as the following:
+</p>
+    <ul>
+        <li>
+            Files stored on the actual device.
+        </li>
+        <li>
+            Streams from sockets.
+        </li>
+        <li>
+            Large amounts of data stored in a provider's underlying database system.
+        </li>
+    </ul>
+<p>
+    A content provider for data streams provides access to its data with a file descriptor object
+    such as {@link android.content.res.AssetFileDescriptor} instead of a
+    {@link android.database.Cursor} object. The pasting application reads the data stream using
+    this file descriptor.
+</p>
+<p>
+    To set up your application to copy a data stream with a provider, follow these steps:
+</p>
+<ol>
+    <li>
+        Set up a content URI for the data stream you are putting on the clipboard. Options
+        for doing this include the following:
+        <ul>
+            <li>
+                Encode an identifier for the data stream onto the URI,
+                as described in the section
+                <a href="#Encoding">Encoding an identifier on the URI</a>, and then maintain a
+                table in your provider that contains identifiers and the corresponding stream name.
+            </li>
+            <li>
+                Encode the stream name directly on the URI.
+            </li>
+            <li>
+                Use a unique URI that always returns the current stream from the provider. If you
+                use this option, you have to remember to update your provider to point to a
+                different stream whenever you copy the stream to the clipboard via the URI.
+            </li>
+        </ul>
+    </li>
+    <li>
+        Provide a MIME type for each type of data stream you plan to offer. Pasting applications
+        need this information to determine if they can paste the data on the clipboard.
+    </li>
+    <li>
+        Implement one of the {@link android.content.ContentProvider} methods that returns
+        a file descriptor for a stream. If you encode identifiers on the content URI, use this
+        method to determine which stream to open.
+    </li>
+    <li>
+        To copy the data stream to the clipboard, construct the content URI and place it
+        on the clipboard.
+    </li>
+</ol>
+<p>
+    To paste a data stream, an application gets the clip from the clipboard, gets the URI, and
+    uses it in a call to a {@link android.content.ContentResolver} file descriptor method that
+    opens the stream. The {@link android.content.ContentResolver} method calls the corresponding
+    {@link android.content.ContentProvider} method, passing it the content URI. Your provider
+    returns the file descriptor to {@link android.content.ContentResolver} method. The pasting
+    application then has the responsibility to read the data from the stream.
+</p>
+<p>
+    The following list shows the most important file descriptor methods for a content provider.
+    Each of these has a corresponding {@link android.content.ContentResolver} method with the
+    string &quot;Descriptor&quot; appended to the method name; for example, the
+    {@link android.content.ContentResolver} analog of
+    {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()} is
+{@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String) openAssetFileDescriptor()}:
+</p>
+<dl>
+    <dt>
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}
+    </dt>
+    <dd>
+        This method should return an asset file descriptor, but only if the provided MIME type is
+        supported by the provider. The caller (the application doing the pasting) provides a MIME
+        type pattern. The content provider (of the application that has copied a URI to the
+        clipboard) returns an {@link android.content.res.AssetFileDescriptor} file handle if it
+        can provide that MIME type, or throws an exception if it can not.
+        <p>
+            This method handles subsections of files. You can use it to read assets that the
+            content provider has copied to the clipboard.
+        </p>
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}
+    </dt>
+    <dd>
+        This method is a more general form of
+{@link android.content.ContentProvider#openTypedAssetFile(Uri,String,Bundle) openTypedAssetFile()}.
+        It does not filter for allowed MIME types, but it can read subsections of files.
+    </dd>
+    <dt>
+        {@link android.content.ContentProvider#openFile(Uri, String) openFile()}
+    </dt>
+    <dd>
+        This is a more general form of
+        {@link android.content.ContentProvider#openAssetFile(Uri, String) openAssetFile()}. It can't
+        read subsections of files.
+    </dd>
+</dl>
+<p>
+    You can optionally use the
+{@link android.content.ContentProvider#openPipeHelper(Uri, String, Bundle, T, ContentProvider.PipeDataWriter) openPipeHelper()}
+    method with your file descriptor method. This allows the pasting application to read the
+    stream data in a background thread using a pipe. To use this method, you need to implement the
+    {@link android.content.ContentProvider.PipeDataWriter} interface. An example of doing this is
+    given in the <a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a> sample
+    application, in the <code>openTypedAssetFile()</code> method of
+    <code>NotePadProvider.java</code>.
+</p>
+<h2 id="DataDesign">Designing Effective Copy/Paste Functionality</h2>
+<p>
+    To design effective copy and paste functionality for your application, remember these
+    points:
+</p>
+    <ul>
+        <li>
+            At any time, there is only one clip on the clipboard. A new copy operation by
+            any application in the system overwrites the previous clip. Since the user may
+            navigate away from your application and do a copy before returning, you can't assume
+            that the clipboard contains the clip that the user previously copied in <em>your</em>
+            application.
+        </li>
+        <li>
+            The intended purpose of multiple {@link android.content.ClipData.Item}
+            objects per clip is to support copying and pasting of multiple selections rather than
+            different forms of reference to a single selection. You usually want all of the
+           {@link android.content.ClipData.Item} objects in a clip to have the same form, that is,
+           they should all be simple text, content URI, or {@link android.content.Intent}, but not
+           a mixture.
+        </li>
+        <li>
+            When you provide data, you can offer different MIME representations. Add the MIME types
+            you support to the {@link android.content.ClipDescription}, and then
+            implement the MIME types in your content provider.
+        </li>
+        <li>
+            When you get data from the clipboard, your application is responsible for checking the
+            available MIME types and then deciding which one, if any, to use. Even if there is a
+            clip on the clipboard and the user requests a paste, your application is not required
+            to do the paste. You <em>should</em> do the paste if the MIME type is compatible. You
+            may choose to coerce the data on the clipboard to text using
+            {@link android.content.ClipData.Item#coerceToText(Context) coerceToText()} if you
+            choose. If your application supports more than one of the available MIME types, you can
+            allow the user to choose which one to use.
+        </li>
+    </ul>
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
new file mode 100644 (file)
index 0000000..588b05b
--- /dev/null
@@ -0,0 +1,995 @@
+page.title=Dragging and Dropping
+@jd:body
+<div id="qv-wrapper">
+    <div id="qv">
+        <h2>Quickview</h2>
+            <ul>
+                <li>
+                    Allow users to move data within your Activity layout using graphical gestures.
+                </li>
+                <li>
+                    Supports operations besides data movement.
+                </li>
+                <li>
+                    Only works within a single application.
+                </li>
+                <li>
+                    Requires API 11.
+                </li>
+            </ul>
+        <h2>In this document</h2>
+        <ol>
+            <li>
+                <a href="#AboutDragging">Overview</a>
+                <ol>
+                    <li>
+                        <a href="#DragDropLifecycle">The drag/drop process</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragListeners">The drag event listener and callback method</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragEvent">Drag events</a>
+                    </li>
+                    <li>
+                        <a href="#AboutDragShadowBuilder">
+                        The drag shadow</a>
+                    </li>
+                </ol>
+            </li>
+            <li>
+                <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>
+                <ol>
+                    <li>
+                        <a href="#StartDrag">Starting a drag</a>
+                    </li>
+                    <li>
+                        <a href="#HandleStart">Responding to a drag start</a>
+                    </li>
+                    <li>
+                        <a href="#HandleDuring">Handling events during the drag</a>
+                    </li>
+                    <li>
+                        <a href="#HandleDrop">Responding to a drop</a>
+                    </li>
+                    <li>
+                        <a href="#HandleEnd">Responding to a drag end</a>
+                    </li>
+                    <li>
+                        <a href="#RespondEventSample">Responding to drag events: an example</a>
+                    </li>
+                </ol>
+            </li>
+        </ol>
+        <h2>Key classes</h2>
+        <ol>
+            <li>
+                {@link android.view.View View}
+            </li>
+            <li>
+                {@link android.view.View.OnLongClickListener OnLongClickListener}
+            </li>
+            <li>
+                {@link android.view.View.OnDragListener OnDragListener}
+            </li>
+            <li>
+                {@link android.view.DragEvent DragEvent}
+            </li>
+            <li>
+                {@link android.view.View.DragShadowBuilder DragShadowBuilder}
+            </li>
+            <li>
+                {@link android.content.ClipData ClipData}
+            </li>
+            <li>
+                {@link android.content.ClipDescription ClipDescription}
+            </li>
+        </ol>
+        <h2>Related Samples</h2>
+        <ol>
+            <li>
+                <a href="{@docRoot}resources/samples/Honeycomb-Gallery/index.html">
+                Honeycomb-Gallery</a> sample application.
+            </li>
+            <li>
+                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DragAndDropDemo.html">
+DragAndDropDemo.java</a> and
+                <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/DraggableDot.html">
+DraggableDot.java</a> in <a href="{@docRoot}resources/samples/ApiDemos/index.html">Api Demos</a>.
+            </li>
+        </ol>
+        <h2>See also</h2>
+        <ol>
+            <li>
+            <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
+            </li>
+            <li>
+                <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
+            </li>
+        </ol>
+    </div>
+</div>
+<p>
+    With the Android drag/drop framework, you can allow your users to move data
+    from one View to another View in the current layout using a graphical drag and drop gesture.
+    The framework includes a drag event class, drag listeners, and helper methods and classes.
+</p>
+<p>
+    Although the framework is primarily designed for data movement, you can use
+    it for other UI actions. For example, you could create an app that mixes colors when the user
+    drags a color icon over another icon. The rest of this topic, however, describes the
+    framework in terms of data movement.
+</p>
+<h2 id="AboutDragging">Overview</h2>
+<p>
+    A drag and drop operation starts when the user makes some gesture that you recognize as a
+    signal to start dragging data. In response, your application tells the system that the drag is
+    starting. The system calls back to your application to get a representation of the data
+    being dragged. As the user's finger moves this representation (a &quot;drag shadow&quot;)
+    over the current layout, the system sends drag events to the drag event listener objects and
+    drag event callback methods associated with the {@link android.view.View} objects in the layout.
+    Once the user releases the drag shadow, the system ends the drag operation.
+</p>
+<p>
+    You create a drag event listener object (&quot;listeners&quot;) from a class that implements
+    {@link android.view.View.OnDragListener}. You set the drag event listener object for a View
+    with the View object's
+    {@link android.view.View#setOnDragListener(View.OnDragListener) setOnDragListener()} method.
+    Each View object also has a {@link android.view.View#onDragEvent(DragEvent) onDragEvent()}
+    callback method. Both of these are described in more detail in the section
+    <a href="#AboutDragListeners">The drag event listener and callback method</a>.
+</p>
+<p class="note">
+    <strong>Note</strong>: For the sake of simplicity, the following sections refer to the routine
+    that receives drag events as the &quot;drag event listener&quot;, even though it may actually
+    be a callback method.
+</p>
+<p>
+    When you start a drag, you include both the data you are moving and metadata describing this
+    data as part of the call to the system. During the drag, the system sends drag events to the
+    drag event listeners or callback methods of each View in the layout. The listeners or callback
+    methods can use the metadata to decide if they want to accept the data when it is dropped.
+    If the user drops the data over a View object, and that View object's listener or callback
+    method has previously told the system that it wants to accept the drop, then the system sends
+    the data to the listener or callback method in a drag event.
+</p>
+<p>
+    Your application tells the system to start a drag by calling the
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    method. This tells the system to start sending drag events. The method also sends the data that
+    you are dragging.
+</p>
+<p>
+    You can call
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+    for any attached View in the current layout. The system only uses the View object to get access
+    to global settings in your layout.
+</p>
+<p>
+    Once your application calls
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    the rest of the process uses events that the system sends to the View objects in your current
+    layout.
+</p>
+<h3 id="DragDropLifecycle">The drag/drop process</h3>
+<p>
+    There are basically four steps or states in the drag and drop process:
+</p>
+<dl>
+    <dt>
+        <em>Started</em>
+    </dt>
+    <dd>
+        In response to the user's gesture to begin a drag, your application calls
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        to tell the system to start a drag. The arguments
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        provide the data to be dragged, metadata for this data, and a callback for drawing the
+        drag shadow.
+        <p>
+            The system first responds by calling back to your application to get a drag shadow. It
+            then displays the drag shadow on the device.
+        </p>
+        <p>
+            Next, the system sends a drag event with action type
+            {@link android.view.DragEvent#ACTION_DRAG_STARTED} to the drag event listeners for
+            all the View objects in the current layout. To continue to receive drag events,
+            including a possible drop event, a drag event listener must return <code>true</code>.
+            This registers the listener with the system. Only registered listeners continue to
+            receive drag events. At this point, listeners can also change the appearance of their
+            View object to show that the listener can accept a drop event.
+        </p>
+        <p>
+            If the drag event listener returns <code>false</code>, then it will not receive drag
+            events for the current operation until the system sends a drag event with action type
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED}. By sending <code>false</code>, the
+            listener tells the system that it is not interested in the drag operation and
+            does not want to accept the dragged data.
+        </p>
+    </dd>
+    <dt>
+        <em>Continuing</em>
+    </dt>
+    <dd>
+        The user continues the drag. As the drag shadow intersects the bounding box of a View
+        object, the system sends one or more drag events to the View object's drag event
+        listener (if it is registered to receive events). The listener may choose to
+        alter its View object's appearance in response to the event. For example, if the event
+        indicates that the drag shadow has entered the bounding box of the View
+        (action type {@link android.view.DragEvent#ACTION_DRAG_ENTERED}), the listener
+        can react by highlighting its View.
+    </dd>
+    <dt>
+        <em>Dropped</em>
+    </dt>
+    <dd>
+        The user releases the drag shadow within the bounding box of a View that can accept the
+        data. The system sends the View object's listener a drag event with action type
+        {@link android.view.DragEvent#ACTION_DROP}. The drag event contains the data that was
+        passed to the system in the call to
+        {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}
+        that started the operation. The listener is expected to return boolean <code>true</code> to
+        the system if code for accepting the drop succeeds.
+        <p>
+            Note that this step only occurs if the user drops the drag shadow within the bounding
+            box of a View whose listener is registered to receive drag events. If the user releases
+            the drag shadow in any other situation, no {@link android.view.DragEvent#ACTION_DROP}
+            drag event is sent.
+        </p>
+    </dd>
+    <dt>
+        <em>Ended</em>
+    </dt>
+    <dd>
+        After the user releases the drag shadow, and after the system sends out (if necessary)
+        a drag event with action type {@link android.view.DragEvent#ACTION_DROP}, the system sends
+        out a drag event with action type {@link android.view.DragEvent#ACTION_DRAG_ENDED} to
+        indicate that the drag operation is over. This is done regardless of where the user released
+        the drag shadow. The event is sent to every listener that is registered to receive drag
+        events, even if the listener received the {@link android.view.DragEvent#ACTION_DROP} event.
+    </dd>
+</dl>
+<p>
+    Each of these four steps is described in more detail in the section
+    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
+</p>
+<h3 id="AboutDragListeners">The drag event listener and callback method</h3>
+<p>
+    A View receives drag events with either a drag event listener that implements
+    {@link android.view.View.OnDragListener} or with its
+    {@link android.view.View#onDragEvent(DragEvent)} callback method.
+    When the system calls the method or listener, it passes to them
+    a {@link android.view.DragEvent} object.
+</p>
+<p>
+    You will probably want to use the listener in most cases. When you design UIs, you usually
+    don't subclass View classes, but using the callback method forces you to do this in order to
+    override the method. In comparison, you can implement one listener class and then use it with
+    several different View objects. You can also implement it as an anonymous inline class. To
+    set the listener for a View object, call
+{@link android.view.View#setOnDragListener(android.view.View.OnDragListener) setOnDragListener()}.
+</p>
+<p>
+    You can have both a listener and a callback method for View object. If this occurs,
+    the system first calls the listener. The system doesn't call the callback method unless the
+    listener returns <code>false</code>.
+</p>
+<p>
+    The combination of the {@link android.view.View#onDragEvent(DragEvent)} method and
+    {@link android.view.View.OnDragListener} is analogous to the combination
+    of the {@link android.view.View#onTouchEvent(MotionEvent) onTouchEvent()} and
+    {@link android.view.View.OnTouchListener} used with touch events.
+</p>
+<h3 id="AboutDragEvent">Drag events</h3>
+<p>
+    The system sends out a drag event in the form of a {@link android.view.DragEvent} object. The
+    object contains an action type that tells the listener what is happening in the drag/drop
+    process. The object contains other data, depending on the action type.
+</p>
+<p>
+    To get the action type, a listener calls {@link android.view.DragEvent#getAction()}. There
+    are six possible values, defined by constants in the {@link android.view.DragEvent} class. These
+    are listed in <a href="table1">table 1</a>.
+</p>
+<p>
+    The {@link android.view.DragEvent} object also contains the data that your application provided
+    to the system in the call to
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    Some of the data is valid only for certain action types. The data that is valid for each action
+    type is summarized in <a href="table2">table 2</a>. It is also described in detail with
+    the event for which it is valid in the section
+    <a href="#DesignDragOperation">Designing a Drag and Drop Operation</a>.
+</p>
+<p class="table-caption" id="table1">
+  <strong>Table 1.</strong> DragEvent action types
+</p>
+<table>
+    <tr>
+        <th scope="col">getAction() value</th>
+        <th scope="col">Meaning</th>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
+        <td>
+            A View object's drag event listener receives this event action type just after the
+            application calls
+{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()} and
+            gets a drag shadow.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
+        <td>
+            A View object's drag event listener receives this event action type when the drag shadow
+            has just entered the bounding box of the View. This is the first event action type the
+            listener receives when the drag shadow enters the bounding box. If the listener wants to
+            continue receiving drag events for this operation, it must return boolean
+            <code>true</code> to the system.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
+        <td>
+            A View object's drag event listener receives this event action type after it receives a
+            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event while the drag shadow is
+            still within the bounding box of the View.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
+        <td>
+            A View object's drag event listener receives this event action type after it receives a
+            {@link android.view.DragEvent#ACTION_DRAG_ENTERED} and at least one
+            {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event, and after the user has moved
+            the drag shadow outside the bounding box of the View.
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
+        <td>
+            A View object's drag event listener receives this event action type when the user
+            releases the drag shadow over the View object. This action type is only sent to a View
+            object's listener if the listener returned boolean <code>true</code> in response to the
+            {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event. This action type is not
+            sent if the user releases the drag shadow on a View whose listener is not registered,
+            or if the user releases the drag shadow on anything that is not part of the current
+            layout.
+            <p>
+                The listener is expected to return boolean <code>true</code> if it successfully
+                processes the drop. Otherwise, it should return <code>false</code>.
+            </p>
+        </td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
+        <td>
+            A View object's drag event listener receives this event action type
+            when the system is ending the drag operation. This action type is not necessarily
+            preceded by an {@link android.view.DragEvent#ACTION_DROP} event. If the system sent
+            a {@link android.view.DragEvent#ACTION_DROP}, receiving the
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED} action type does not imply that the
+            drop operation succeeded. The listener must call
+            {@link android.view.DragEvent#getResult()} to get the value that was
+            returned in response to {@link android.view.DragEvent#ACTION_DROP}. If an
+            {@link android.view.DragEvent#ACTION_DROP} event was not sent, then
+            {@link android.view.DragEvent#getResult()} returns <code>false</code>.
+        </td>
+    </tr>
+</table>
+<p class="table-caption" id="table2">
+  <strong>Table 2.</strong> Valid DragEvent data by action type</p>
+<table>
+    <tr>
+        <th scope="col">{@link android.view.DragEvent#getAction()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getClipDescription()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getLocalState()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getX()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getY()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getClipData()} value</th>
+        <th scope="col">{@link android.view.DragEvent#getResult()} value</th>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_STARTED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENTERED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_LOCATION}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_EXITED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DROP}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+    </tr>
+    <tr>
+        <td>{@link android.view.DragEvent#ACTION_DRAG_ENDED}</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">X</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">&nbsp;</td>
+        <td style="text-align: center;">X</td>
+    </tr>
+</table>
+<p>
+    The {@link android.view.DragEvent#getAction()},
+    {@link android.view.DragEvent#describeContents()},
+    {@link android.view.DragEvent#writeToParcel(Parcel,int) writeToParcel()}, and
+    {@link android.view.DragEvent#toString()} methods always return valid data.
+</p>
+<p>
+    If a method does not contain valid data for a particular action type, it returns either
+    <code>null</code> or 0, depending on its result type.
+</p>
+<h3 id="AboutDragShadowBuilder">
+    The drag shadow
+</h3>
+<p>
+    During a drag and drop operation, the system displays a image that the user drags.
+    For data movement, this image represents the data being dragged. For other operations, the
+    image represents some aspect of the drag operation.
+</p>
+<p>
+    The image is called a drag shadow. You create it with methods you declare for a
+    {@link android.view.View.DragShadowBuilder} object, and then pass it to the system when you
+    start a drag using
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}.
+    As part of its response to
+    {@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()},
+    the system invokes the callback methods you've defined in
+    {@link android.view.View.DragShadowBuilder} to obtain a drag shadow.
+</p>
+<p>
+    The {@link android.view.View.DragShadowBuilder} class has two constructors:
+</p>
+    <dl>
+    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)}</dt>
+    <dd>
+        This constructor accepts any of your application's
+        {@link android.view.View} objects. The constructor stores the View object
+        in the {@link android.view.View.DragShadowBuilder} object, so during
+        the callback you can access it as you construct your drag shadow.
+        It doesn't have to be associated with the View (if any) that the user
+        selected to start the drag operation.
+        <p>
+            If you use this constructor, you don't have to extend
+            {@link android.view.View.DragShadowBuilder} or override its methods. By default,
+            you will get a drag shadow that has the same appearance as the View you pass as an
+            argument, centered under the location where the user is touching the screen.
+        </p>
+    </dd>
+    <dt>{@link android.view.View.DragShadowBuilder#View.DragShadowBuilder()}</dt>
+    <dd>
+        If you use this constructor, no View object is available in the
+        {@link android.view.View.DragShadowBuilder} object (the field is set to <code>null</code>).
+        If you use this constructor, and you don't extend
+        {@link android.view.View.DragShadowBuilder} or override its methods,
+        you will get an invisible drag shadow.
+        The system does <em>not</em> give an error.
+    </dd>
+</dl>
+<p>
+    The {@link android.view.View.DragShadowBuilder} class has two methods:
+</p>
+<dl>
+    <dt>
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+    </dt>
+    <dd>
+        The system calls this method immediately after you call
+{@link android.view.View#startDrag(ClipData,View.DragShadowBuilder,Object,int) startDrag()}. Use it
+        to send to the system the dimensions and touch point of the drag shadow. The method has two
+        arguments:
+        <dl>
+            <dt><em>dimensions</em></dt>
+            <dd>
+                A {@link android.graphics.Point} object. The drag shadow width goes in
+                {@link android.graphics.Point#x} and its height goes in
+                {@link android.graphics.Point#y}.
+            </dd>
+            <dt><em>touch_point</em></dt>
+            <dd>
+                A {@link android.graphics.Point} object. The touch point is the location within the
+                drag shadow that should be under the user's finger during the drag. Its X
+                position goes in {@link android.graphics.Point#x} and its Y position goes in
+                {@link android.graphics.Point#y}
+            </dd>
+        </dl>
+    </dd>
+    <dt>
+       {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()}
+    </dt>
+    <dd>
+        Immediately after the call to
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+        the system calls
+        {@link android.view.View.DragShadowBuilder#onDrawShadow(Canvas) onDrawShadow()} to get the
+        drag shadow itself. The method has a single argument, a {@link android.graphics.Canvas}
+        object that the system constructs from the parameters you provide in
+{@link android.view.View.DragShadowBuilder#onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()}
+        Use it to draw the drag shadow in the provided {@link android.graphics.Canvas} object.
+    </dd>
+</dl>
+<p>
+    To improve performance, you should keep the size of the drag shadow small. For a single item,
+    you may want to use a icon. For a multiple selection, you may want to use icons in a stack
+    rather than full images spread out over the screen.
+</p>
+<h2 id="DesignDragOperation">Designing a Drag and Drop Operation</h2>
+<p>
+    This section shows step-by-step how to start a drag, how to respond to events during
+    the drag, how respond to a drop event, and how to end the drag and drop operation.
+</p>
+<h3 id="StartDrag">Starting a drag</h3>
+<p>
+    The user starts a drag with a drag gesture, usually a long press, on a View object.
+    In response, you should do the following:
+</p>
+<ol>
+     <li>
+        As necessary, create a {@link android.content.ClipData} and
+        {@link android.content.ClipData.Item} for the data being moved. As part of the
+        ClipData object, supply metadata that is stored in a {@link android.content.ClipDescription}
+        object within the ClipData. For a drag and drop operation that does not represent data
+        movement, you may want to use <code>null</code> instead of an actual object.
+        <p>
+            For example, this code snippet shows how to respond to a long press on a ImageView
+            by creating a ClipData object that contains the tag or label of an
+            ImageView. Following this snippet, the next snippet shows how to override the methods in
+            {@link android.view.View.DragShadowBuilder}:
+        </p>
+<pre>
+// Create a string for the ImageView label
+private static final String IMAGEVIEW_TAG = &quot;icon bitmap&quot;
+
+// Creates a new ImageView
+ImageView imageView = new ImageView(this);
+
+// Sets the bitmap for the ImageView from an icon bit map (defined elsewhere)
+imageView.setImageBitmap(mIconBitmap);
+
+// Sets the tag
+imageView.setTag(IMAGEVIEW_TAG);
+
+    ...
+
+// Sets a long click listener for the ImageView using an anonymous listener object that
+// implements the OnLongClickListener interface
+imageView.setOnLongClickListener(new View.OnLongClickListener() {
+
+    // Defines the one method for the interface, which is called when the View is long-clicked
+    public boolean onLongClick(View v) {
+
+    // Create a new ClipData.
+    // This is done in two steps to provide clarity. The convenience method
+    // ClipData.newPlainText() can create a plain text ClipData in one step.
+
+    // Create a new ClipData.Item from the ImageView object's tag
+    ClipData.Item item = new ClipData.Item(v.getTag());
+
+    // Create a new ClipData using the tag as a label, the plain text MIME type, and
+    // the already-created item. This will create a new ClipDescription object within the
+    // ClipData, and set its MIME type entry to &quot;text/plain&quot;
+    ClipData dragData = new ClipData(v.getTag(),ClipData.MIMETYPE_TEXT_PLAIN,item);
+
+    // Instantiates the drag shadow builder.
+    View.DrawShadowBuilder myShadow = new MyDragShadowBuilder(imageView);
+
+    // Starts the drag
+
+            v.startDrag(dragData,  // the data to be dragged
+                        myShadow,  // the drag shadow builder
+                        null,      // no need to use local data
+                        0          // flags (not currently used, set to 0)
+            );
+
+    }
+}
+</pre>
+    </li>
+    <li>
+        The following code snippet defines {@code myDragShadowBuilder}
+        It creates a drag shadow for dragging a TextView as a small gray rectangle:
+<pre>
+    private static class MyDragShadowBuilder extends View.DragShadowBuilder {
+
+    // The drag shadow image, defined as a drawable thing
+    private static Drawable shadow;
+
+        // Defines the constructor for myDragShadowBuilder
+        public MyDragShadowBuilder(View v) {
+
+            // Stores the View parameter passed to myDragShadowBuilder.
+            super(v);
+
+            // Creates a draggable image that will fill the Canvas provided by the system.
+            shadow = new ColorDrawable(Color.LTGRAY);
+        }
+
+        // Defines a callback that sends the drag shadow dimensions and touch point back to the
+        // system.
+        &#64;Override
+        public void onProvideShadowMetrics (Point size, Point touch)
+            // Defines local variables
+            private int width, height;
+
+            // Sets the width of the shadow to half the width of the original View
+            width = getView().getWidth() / 2;
+
+            // Sets the height of the shadow to half the height of the original View
+            height = getView().getHeight() / 2;
+
+            // The drag shadow is a ColorDrawable. This sets its dimensions to be the same as the
+            // Canvas that the system will provide. As a result, the drag shadow will fill the
+            // Canvas.
+            shadow.setBounds(0, 0, width, height);
+
+            // Sets the size parameter's width and height values. These get back to the system
+            // through the size parameter.
+            size.set(width, height);
+
+            // Sets the touch point's position to be in the middle of the drag shadow
+            touch.set(width / 2, height / 2);
+        }
+
+        // Defines a callback that draws the drag shadow in a Canvas that the system constructs
+        // from the dimensions passed in onProvideShadowMetrics().
+        &#64;Override
+        public void onDrawShadow(Canvas canvas) {
+
+            // Draws the ColorDrawable in the Canvas passed in from the system.
+            shadow.draw(canvas);
+        }
+    }
+</pre>
+        <p class="note">
+            <strong>Note:</strong> Remember that you don't have to extend
+            {@link android.view.View.DragShadowBuilder}. The constructor
+            {@link android.view.View.DragShadowBuilder#View.DragShadowBuilder(View)} creates a
+            default drag shadow that's the same size as the View argument passed to it, with the
+            touch point centered in the drag shadow.
+        </p>
+    </li>
+</ol>
+<h3 id="HandleStart">Responding to a drag start</h3>
+<p>
+    During the drag operation, the system dispatches drag events to the drag event listeners
+    of the View objects in the current layout. The listeners should react
+    by calling {@link android.view.DragEvent#getAction()} to get the action type.
+    At the start of a drag, this methods returns {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
+</p>
+<p>
+    In response to an event with the action type {@link android.view.DragEvent#ACTION_DRAG_STARTED},
+    a listener should do the following:
+</p>
+<ol>
+    <li>
+        Call {@link android.view.DragEvent#getClipDescription()} to get the
+        {@link android.content.ClipDescription}. Use the MIME type methods in
+        {@link android.content.ClipDescription} to see if the listener can accept the data being
+        dragged.
+        <p>
+            If the drag and drop operation does not represent data movement, this may not be
+            necessary.
+        </p>
+    </li>
+    <li>
+        If the listener can accept a drop, it should return <code>true</code>. This tells
+        the system to continue to send drag events to the listener.
+        If it can't accept a drop, it should return <code>false</code>, and the system
+        will stop sending drag events until it sends out
+        {@link android.view.DragEvent#ACTION_DRAG_ENDED}.
+    </li>
+</ol>
+<p>
+    Note that for an {@link android.view.DragEvent#ACTION_DRAG_STARTED} event, these
+    the following {@link android.view.DragEvent} methods are not valid:
+    {@link android.view.DragEvent#getClipData()}, {@link android.view.DragEvent#getX()},
+    {@link android.view.DragEvent#getY()}, and {@link android.view.DragEvent#getResult()}.
+</p>
+<h3 id="HandleDuring">Handling events during the drag</h3>
+<p>
+    During the drag, listeners that returned <code>true</code> in response to
+    the {@link android.view.DragEvent#ACTION_DRAG_STARTED} drag event continue to receive drag
+    events. The types of drag events a listener receives during the drag depend on the location of
+    the drag shadow and the visibility of the listener's View.
+</p>
+<p>
+    During the drag, listeners primarily use drag events to decide if they should change the
+    appearance of their View.
+</p>
+<p>
+    During the drag, {@link android.view.DragEvent#getAction()} returns one of three
+    values:
+</p>
+<ul>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED}:
+        The listener receives this when the touch point
+        (the point on the screen underneath the user's finger) has entered the bounding box of the
+        listener's View.
+    </li>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}: Once the listener receives an
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} event, and before it receives an
+        A{@link android.view.DragEvent#ACTION_DRAG_EXITED} event, it receives a new
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION} event every time the touch point moves.
+        The {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()} methods
+        return the the X and Y coordinates of the touch point.
+    </li>
+    <li>
+        {@link android.view.DragEvent#ACTION_DRAG_EXITED}:  This event is sent to a listener that
+        previously received {@link android.view.DragEvent#ACTION_DRAG_ENTERED}, after
+        the drag shadow is no longer within the bounding box of the listener's View.
+    </li>
+</ul>
+<p>
+    The listener does not need to react to any of these action types. If the listener returns a
+    value to the system, it is ignored. Here are some guidelines for responding to each of
+    these action types:
+</p>
+<ul>
+    <li>
+        In response to {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}, the listener can change the appearance
+        of the View to indicate that it is about to receive a drop.
+    </li>
+    <li>
+        An event with the action type {@link android.view.DragEvent#ACTION_DRAG_LOCATION} contains
+        valid data for {@link android.view.DragEvent#getX()} and
+        {@link android.view.DragEvent#getY()}, corresponding to the location of the touch point.
+        The listener may want to use this information to alter the appearance of that part of the
+        View that is at the touch point. The listener can also use this information
+        to determine the exact position where the user is going to drop the drag shadow.
+    </li>
+    <li>
+        In response to {@link android.view.DragEvent#ACTION_DRAG_EXITED}, the listener should reset
+        any appearance changes it applied in response to
+        {@link android.view.DragEvent#ACTION_DRAG_ENTERED} or
+        {@link android.view.DragEvent#ACTION_DRAG_LOCATION}. This indicates to the user that
+        the View is no longer an imminent drop target.
+    </li>
+</ul>
+<h3 id="HandleDrop">Responding to a drop</h3>
+<p>
+    When the user releases the drag shadow on a View in the application, and that View previously
+    reported that it could accept the content being dragged, the system dispatches a drag event
+    to that View with the action type {@link android.view.DragEvent#ACTION_DROP}. The listener
+    should do the following:
+</p>
+<ol>
+    <li>
+        Call {@link android.view.DragEvent#getClipData()} to get the
+        {@link android.content.ClipData} object that was originally supplied in the call
+        to
+{@link android.view.View#startDrag(ClipData, View.DragShadowBuilder, Object, int) startDrag()}
+        and store it. If the drag and drop operation does not represent data movement,
+        this may not be necessary.
+    </li>
+    <li>
+        Return boolean <code>true</code> to indicate that the drop was processed successfully, or
+        boolean <code>false</code> if it was not. The returned value becomes the value returned by
+        {@link android.view.DragEvent#getResult()} for an
+        {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
+        <p>
+            Note that if the system does not send out an {@link android.view.DragEvent#ACTION_DROP}
+            event, the value of {@link android.view.DragEvent#getResult()} for an
+            {@link android.view.DragEvent#ACTION_DRAG_ENDED} event is <code>false</code>.
+        </p>
+    </li>
+</ol>
+<p>
+    For an {@link android.view.DragEvent#ACTION_DROP} event,
+    {@link android.view.DragEvent#getX()} and {@link android.view.DragEvent#getY()}
+    return the X and Y position of the drag point at the moment of the drop, using the coordinate
+    system of the View that received the drop.
+</p>
+<p>
+    The system does allow the user to release the drag shadow on a View whose listener is not
+    receiving drag events. It will also allow the user to release the drag shadow
+    on empty regions of the application's UI, or on areas outside of your application.
+    In all of these cases, the system does not send an event with action type
+    {@link android.view.DragEvent#ACTION_DROP}, although it does send out an
+    {@link android.view.DragEvent#ACTION_DRAG_ENDED} event.
+</p>
+<h3 id="HandleEnd">Responding to a drag end</h3>
+<p>
+    Immediately after the user releases the drag shadow, the system sends a
+    drag event to all of the drag event listeners in your application, with an action type of
+    {@link android.view.DragEvent#ACTION_DRAG_ENDED}. This indicates that the drag operation is
+    over.
+</p>
+<p>
+    Each listener should do the following:
+</p>
+<ol>
+    <li>
+        If listener changed its View object's appearance during the operation, it should reset the
+        View to its default appearance. This is a visual indication to the user that the operation
+        is over.
+    </li>
+    <li>
+        The listener can optionally call {@link android.view.DragEvent#getResult()} to find out more
+        about the operation. If a listener returned <code>true</code> in response to an event of
+        action type {@link android.view.DragEvent#ACTION_DROP}, then
+        {@link android.view.DragEvent#getResult()} will return boolean <code>true</code>. In all
+        other cases, {@link android.view.DragEvent#getResult()} returns boolean <code>false</code>,
+        including any case in which the system did not send out a
+        {@link android.view.DragEvent#ACTION_DROP} event.
+    </li>
+    <li>
+        The listener should return boolean <code>true</code> to the system.
+    </li>
+</ol>
+<p>
+</p>
+<h3 id="RespondEventSample">Responding to drag events: an example</h3>
+<p>
+    All drag events are initially received by your drag event method or listener. The following
+    code snippet is a simple example of reacting to drag events in a listener:
+</p>
+<pre>
+// Creates a new drag event listener
+mDragListen = new myDragEventListener();
+
+View imageView = new ImageView(this);
+
+// Sets the drag event listener for the View
+imageView.setOnDragListener(mDragListen);
+
+...
+
+protected class myDragEventListener implements View.OnDragEventListener {
+
+    // This is the method that the system calls when it dispatches a drag event to the
+    // listener.
+    public boolean onDrag(View v, DragEvent event) {
+
+        // Defines a variable to store the action type for the incoming event
+        final int action = event.getAction();
+
+        // Handles each of the expected events
+        switch(action) {
+
+            case DragEvent.ACTION_DRAG_STARTED:
+
+                // Determines if this View can accept the dragged data
+                if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
+
+                    // As an example of what your application might do,
+                    // applies a blue color tint to the View to indicate that it can accept
+                    // data.
+                    v.setColorFilter(Color.BLUE);
+
+                    // Invalidate the view to force a redraw in the new tint
+                    v.invalidate();
+
+                    // returns true to indicate that the View can accept the dragged data.
+                    return(true);
+
+                    } else {
+
+                    // Returns false. During the current drag and drop operation, this View will
+                    // not receive events again until ACTION_DRAG_ENDED is sent.
+                    return(false);
+
+                    }
+                break;
+
+            case DragEvent.ACTION_DRAG_ENTERED: {
+
+                // Applies a green tint to the View. Return true; the return value is ignored.
+
+                v.setColorFilter(Color.GREEN);
+
+                // Invalidate the view to force a redraw in the new tint
+                v.invalidate();
+
+                return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_LOCATION:
+
+                // Ignore the event
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_EXITED:
+
+                    // Re-sets the color tint to blue. Returns true; the return value is ignored.
+                    v.setColorFilter(Color.BLUE);
+
+                    // Invalidate the view to force a redraw in the new tint
+                    v.invalidate();
+
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DROP:
+
+                    // Gets the item containing the dragged data
+                    ClipData.Item item = event.getClipData().getItemAt(0);
+
+                    // Gets the text data from the item.
+                    dragData = item.getText();
+
+                    // Displays a message containing the dragged data.
+                    Toast.makeText(this, "Dragged data is " + dragData, Toast.LENGTH_LONG);
+
+                    // Turns off any color tints
+                    v.clearColorFilter();
+
+                    // Invalidates the view to force a redraw
+                    v.invalidate();
+
+                    // Returns true. DragEvent.getResult() will return true.
+                    return(true);
+
+                break;
+
+                case DragEvent.ACTION_DRAG_ENDED:
+
+                    // Turns off any color tinting
+                    v.clearColorFilter();
+
+                    // Invalidates the view to force a redraw
+                    v.invalidate();
+
+                    // Does a getResult(), and displays what happened.
+                    if (event.getResult()) {
+                        Toast.makeText(this, "The drop was handled.", Toast.LENGTH_LONG);
+
+                    } else {
+                        Toast.makeText(this, "The drop didn't work.", Toast.LENGTH_LONG);
+
+                    };
+
+                    // returns true; the value is ignored.
+                    return(true);
+
+                break;
+
+                // An unknown action type was received.
+                default:
+                    Log.e("DragDrop Example","Unknown action type received by OnDragListener.");
+
+                break;
+        };
+    };
+};
+</pre>
\ No newline at end of file
diff --git a/docs/html/images/ui/clipboard/copy_paste_framework.png b/docs/html/images/ui/clipboard/copy_paste_framework.png
new file mode 100755 (executable)
index 0000000..57facaa
Binary files /dev/null and b/docs/html/images/ui/clipboard/copy_paste_framework.png differ