<p>This tutorial is about Android drag and drop feature and how to use it in an Android application with a simple example.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<span class="embed-youtube" style="text-align:center; display: block;"><amp-youtube data-videoid="vD0QsyHfVlE" data-param-rel="1" data-param-showsearch="0" data-param-showinfo="1" data-param-iv_load_policy="1" data-param-fs="1" data-param-hl="en-US" data-param-autohide="2" data-param-wmode="transparent" width="1200" height="675" layout="responsive"><a href="https://www.youtube.com/watch?v=vD0QsyHfVlE" placeholder><amp-img src="https://i.ytimg.com/vi/vD0QsyHfVlE/hqdefault.jpg" alt="YouTube Poster" layout="fill" object-fit="cover"><noscript><img src="https://i.ytimg.com/vi/vD0QsyHfVlE/hqdefault.jpg" loading="lazy" decoding="async" alt="YouTube Poster"></noscript></amp-img></a></amp-youtube></span>
</div></figure>



<div class="wp-block-buttons aligncenter is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link has-white-color has-text-color has-background" href="https://github.com/arunk7839/DragAndDropDemo" style="background-color:#520599" target="_blank" rel="noreferrer noopener"><strong>DOWNLOAD CODE</strong></a></div>
</div>



<p>Android <span style="color: #0000ff;"><strong>Drag and Drop</strong></span> framework, allows you to move data from one View to another using a graphical drag and drop gesture. 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. ;</p>



<h3 class="wp-block-heading"><span style="color: #000080;"><strong>Android drag/drop process</strong></span></h3>



<p>In android, the Drag and Drop process contains 4 steps or states:</p>



<ul class="wp-block-list"><li><span style="color: #0000ff;"><strong>Started</strong></span></li><li><span style="color: #0000ff;"><strong>Continuing</strong></span></li><li><span style="color: #0000ff;"><strong>Dropped</strong></span></li><li><span style="color: #0000ff;"><strong>Ended</strong></span></li></ul>



<h4 class="wp-block-heading"><span style="color: #0000ff;"><strong>Started</strong></span></h4>



<p>In response to the user&#8217;s gesture <strong>(for example, on a long press)</strong> to begin a drag, your application calls <span style="color: #0000ff;"><strong><span style="color: #008000;">startDrag()</span></strong></span> ;to tell the system to start a drag.</p>



<p>The ;<span style="color: #000080;"><strong>startDrag()</strong> ;</span>method arguments will provide data to be dragged, metadata for this data and a call-back for drawing the drag shadow.</p>



<p>After that, the system sends a drag event with action type ;<span style="color: #000080;"><strong>ACTION_DRAG_STARTED</strong></span> ;to the drag event listeners for all the View objects in the current layout. ;</p>



<h4 class="wp-block-heading"><span style="color: #0000ff;"><strong>Continuing</strong></span></h4>



<p>The user continues the drag, and the system now sends <span style="color: #000080;"><strong>ACTION_DRAG_ENTERED</strong></span> ;action followed by ;<span style="color: #000080;"><strong>ACTION_DRAG_LOCATION</strong></span> action to the registered drag event listener for the View. <span style="font-size: inherit;">The listener may choose to alter its View object’s appearance in response to the event or can react by highlighting its View.</span></p>



<p>The drag event listener receives a ;<span style="color: #000080;"><strong>ACTION_DRAG_EXITED</strong></span> ;action after the user has moved the drag shadow outside the bounding box of the View.</p>



<h4 class="wp-block-heading"><span style="color: #0000ff;"><strong>Dropped</strong></span></h4>



<p>User drops the dragged item, and the system sends the <strong><span style="color: #000080;">ACTION_DROP</span> </strong>event only if the user drops the drag shadow within the bounding box of a View which listener is registered to receive drag events.</p>



<p><span style="color: #008000;"><strong>For example:</strong></span> If there are two views <strong>View1</strong> and <strong>View2</strong> and <strong>View1</strong> is registered for dragListener but <strong>view2</strong> is not, then if user drops the item in <strong>View1</strong> then the drop action will be called for <strong>View1</strong> but if user drops the item in <strong>view2</strong> then no drop action will be called for <strong>View2</strong>.</p>



<h4 class="wp-block-heading"><span style="color: #0000ff;"><strong>Ended</strong></span></h4>



<p>The drag-and-drop operation has ended, and the system sends out a drag event with action type <span style="color: #000080;"><strong>ACTION_DRAG_ENDED</strong></span>. All of the views that were listening for the drag-and-drop events now get the ;<strong><span style="color: #000080;">ACTION_DRAG_ENDED</span></strong> event.</p>



<h3 class="wp-block-heading"><span style="color: #000080;"><strong><span class="has-inline-color">OnDragListener</span></strong></span></h3>



<p>To receive the drag-and-drop events, we need to register a ;<strong><span style="color: #008000;">View.OnDragListener</span> ;</strong>on the View using <span style="color: #008000;"><strong>setOnDragListener()</strong></span>.</p>



<p>The ;<span style="color: #008000;"><strong>View.OnDragListener</strong></span> ;having a callback method,<strong><span style="color: #008000;"> onDrag(View v, DragEvent event)</span>.</strong></p>



<ul class="wp-block-list"><li><span style="color: #0000ff;"><strong>v</strong></span>: the <span style="color: #008000;"><strong>view</strong></span> that received the event.</li></ul>



<ul class="wp-block-list"><li><span style="color: #0000ff;"><strong>event</strong></span>: <span style="color: #008000;"><strong>DragEvent</strong></span> ;object, which contains all the information about the drag-and-drop event, including the location of the event, the drag action (state), and the data it carries.</li></ul>



<h3 class="wp-block-heading"><span style="color: #000080;"><strong>Drag events</strong></span></h3>



<p>When ;<span style="color: #000080;"><strong>startDrag() </strong></span>function is called, then the system identifies the type of drag event that is currently taking place and return the drag event to the application. It sends out a drag event in the form of a ;<span style="color: #000080;"><strong>DragEvent </strong></span>object. ;</p>



<p><strong><span style="color: #0000ff;">getAction() </span></strong>is used to identify which type of drag event is taking place.</p>



<p>The DragEvent ;object contains the following different action types:</p>



<ol class="wp-block-list"><li><strong><span style="color: #0000ff;">ACTION_DRAG_STARTED:</span> ;</strong>receives this event action type just after the application calls ;<span style="color: #008000;"><strong>startDrag()</strong></span> ;and gets a drag shadow.</li><li><strong><span style="color: #0000ff;">ACTION_DRAG_ENTERED</span>:</strong> ;receives this event action type when the drag shadow has just entered the bounding box of the View.</li><li><strong><span style="color: #0000ff;">ACTION_DRAG_LOCATION</span>: ;</strong>receives this event action type after it receives a <span style="color: #008000;"><strong>ACTION_DRAG_ENTERED</strong></span> event, when the drag is taking place i.e. the user is dragging the item from one place to other.</li><li><strong><span style="color: #0000ff;">ACTION_DRAG_EXITED</span>: ;</strong> receives this event action type after it receives a ;<strong><span style="color: #008000;">ACTION_DRAG_ENTERED</span></strong> ;and at least one ;<span style="color: #008000;"><strong>ACTION_DRAG_LOCATION</strong></span> ;event, and after the user has moved the drag shadow outside the bounding box of the View.</li><li><strong><span style="color: #0000ff;">ACTION_DROP</span>:</strong> ; receives this event action type when the user releases the drag shadow over the View object. This action type is not sent if the user releases the drag shadow on a View whose listener is not registered. The listener is expected to return boolean <strong><span style="color: #008000;">true</span></strong> if it successfully processes the drop. Otherwise, it should return <span style="color: #008000;"><strong>false</strong></span>.</li><li><strong><span style="color: #0000ff;">ACTION_DRAG_ENDED</span>:</strong> receives this event action type when the system is ending the drag operation. This action type is not necessarily preceded by an ;<span style="color: #008000;"><strong>ACTION_DROP</strong></span> ;event. The listener must call ;<span style="color: #000080;"><strong>getResult()</strong></span> ;to get the value that was returned in response to ;<span style="color: #008000;"><strong>ACTION_DROP</strong></span>. If an ;<strong>ACTION_DROP</strong> ;event was not sent, then ;<strong>getResult()</strong> ;returns ;<strong><span style="color: #008000;">false</span></strong>.</li></ol>



<p>let’s implement the drag and drop feature in our app.</p>



<h3 class="wp-block-heading"><span style="color: #000080;"><strong>Android Drag and Drop Example</strong></span></h3>



<p>In this example, we will drag and drop text view and button from one place to another in a bounding area and outside the bounding area (in another view).</p>



<p>1 . Open the layout file <span style="color: #0000ff;"><strong>activity_main.xml</strong></span> and add the below code. It consist of two LinearLayouts (with equal weight) and the upper LinearLayout consist of a textview and a button.</p>



<p><span style="color: #0000ff;"><strong>activity_main.xml</strong></span></p>



<pre class="wp-block-preformatted"><em><;?</em><strong>xml version="1.0" encoding="utf-8"</strong><em>?>;
</em><;<strong>LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"</strong>>;

 <;<strong>LinearLayout
 android:id="@+id/top_layout"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_weight="1"
 android:background="@color/colorPrimary"
 android:gravity="center"
 android:orientation="vertical"</strong>>;

 <;<strong>Button
 android:id="@+id/btn_draggable"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="@string/btn_text" </strong>/>;

 <;<strong>TextView
 android:id="@+id/tv_draggable"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:layout_marginTop="@dimen/margin_10dp"
 android:text="@string/tv_text"
 android:textColor="@android:color/white"
 android:textSize="20sp"
 android:textStyle="bold" </strong>/>;
 <;/<strong>LinearLayout</strong>>;

 <;<strong>LinearLayout
 android:id="@+id/bottom_layout"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:layout_weight="1"
 android:gravity="center"
 android:background="@color/colorAccent"
 android:orientation="vertical" </strong>/>;

<;/<strong>LinearLayout</strong>>;</pre>



<p>2 . Open <strong><span style="color: #0000ff;">MainActivity.java</span></strong> and add the below code.</p>



<p><span style="color: #0000ff;"><strong>MainActivity.java</strong></span></p>
<!-- WP QUADS Content Ad Plugin v. 2.0.98.1 -->
<div class="quads-location quads-ad2" id="quads-ad2" style="float:none;margin:0px;">

</div>




<pre class="wp-block-preformatted"><strong>package </strong>com.c1ctech.draganddropdemo;

<strong>import </strong>android.content.ClipData;
<strong>import </strong>android.content.ClipDescription;
<strong>import </strong>android.graphics.Color;
<strong>import </strong>android.graphics.PorterDuff;
<strong>import </strong>android.os.Bundle;
<strong>import </strong>android.util.Log;
<strong>import </strong>android.view.DragEvent;
<strong>import </strong>android.view.View;
<strong>import </strong>android.view.ViewGroup;
<strong>import </strong>android.widget.Button;
<strong>import </strong>android.widget.LinearLayout;
<strong>import </strong>android.widget.TextView;
<strong>import </strong>android.widget.Toast;

<strong>import </strong>androidx.appcompat.app.AppCompatActivity;

<strong>public class </strong>MainActivity <strong>extends </strong>AppCompatActivity <strong>implements </strong>View.OnLongClickListener, View.OnDragListener {

 TextView <strong>textView</strong>;
 Button <strong>button</strong>;

 <em><span style="color: #008000;"><strong>// Create a string for the TextView and Button label</strong></span>
</em> <strong>private static final </strong>String <strong><em>TEXTVIEW_TAG </em></strong>= <strong>"DRAG TEXT"</strong>;
 <strong>private static final </strong>String <strong><em>BUTTON_TAG </em></strong>= <strong>"DRAG BUTTON"</strong>;

 @Override
 <strong>protected void </strong>onCreate(Bundle savedInstanceState) {
 <strong>super</strong>.onCreate(savedInstanceState);
 setContentView(R.layout.<strong><em>activity_main</em></strong>);

 <em><strong><span style="color: #008000;">//find views by id</span></strong>
</em> <strong>textView </strong>= findViewById(R.id.<strong><em>tv_draggable</em></strong>);
 <strong>button </strong>= findViewById(R.id.<strong><em>btn_draggable</em></strong>);

 <em><strong><span style="color: #008000;">// Sets the tag</span></strong>
</em> <strong>textView</strong>.setTag(<strong><em>TEXTVIEW_TAG</em></strong>);
 <strong>button</strong>.setTag(<strong><em>BUTTON_TAG</em></strong>);

 implementEvents();
 }

 <em><span style="color: #008000;"><strong>//Implement long click and drag listener</strong></span>
</em> <strong>private void </strong>implementEvents() {

 <strong>textView</strong>.setOnLongClickListener(<strong>this</strong>);
 <strong>button</strong>.setOnLongClickListener(<strong>this</strong>);

 findViewById(R.id.<strong><em>top_layout</em></strong>).setOnDragListener(<strong>this</strong>);
 findViewById(R.id.<strong><em>bottom_layout</em></strong>).setOnDragListener(<strong>this</strong>);
 }


 <strong><span style="color: #008000;"> <em>// This is the method that the system calls when it dispatches a drag event to the
</em></span></strong><em><strong><span style="color: #008000;"> // listener.</span></strong>
</em> @Override
 <strong>public boolean </strong>onDrag(View view, DragEvent dragEvent) {
 <em><strong><span style="color: #008000;">// Defines a variable to store the action type for the incoming event</span></strong>
</em> <strong>int </strong>action = dragEvent.getAction();

 <em><strong><span style="color: #008000;">// Handles each of the expected events</span></strong>
</em> <strong>switch </strong>(action) {
 <strong>case </strong>DragEvent.<strong><em>ACTION_DRAG_STARTED</em></strong>:

 <em><strong><span style="color: #008000;">// Determines if this View can accept the dragged data</span></strong>
</em> <strong>if </strong>(dragEvent.getClipDescription().hasMimeType(ClipDescription.<strong><em>MIMETYPE_TEXT_PLAIN</em></strong>)) {
 <em>/<strong><span style="color: #008000;">/ if you want to apply color when drag started to your view you can uncomment below lines</span></strong>
</em><strong><span style="color: #008000;"><em> // to give any color tint to the View to indicate that it can accept
</em></span></strong><em><strong><span style="color: #008000;"> // data.</span></strong>
</em><strong><span style="color: #0000ff;"><em> //view.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
</em></span></strong><em>
<span style="color: #008000;"><strong> // Invalidate the view to force a redraw in the new tint</strong></span>
</em><strong><span style="color: #0000ff;"><em> // view.invalidate();
</em></span></strong><em>
</em><strong><span style="color: #008000;"><em> // returns true to indicate that the View can accept the dragged data.
</em></span> return true</strong>;
 }

 <strong><span style="color: #008000;"><em>// Returns false. During the current drag and drop operation, this View will
</em></span></strong><em><strong><span style="color: #008000;"> // not receive events again until ACTION_DRAG_ENDED is sent.</span></strong>
</em> <strong>return false</strong>;

 <strong>case </strong>DragEvent.<strong><em>ACTION_DRAG_ENTERED</em></strong>:

 <span style="color: #008000;"><strong><em>// Applies a MAGENTA or any color tint to the View,
 // Return true; the return value is ignored.
</em></strong></span><em>
</em> view.getBackground().setColorFilter(Color.<strong><em>MAGENTA</em></strong>, PorterDuff.Mode.<strong><em>SRC_IN</em></strong>);

 <em><strong><span style="color: #008000;">// Invalidate the view to force a redraw in the new tint</span></strong>
</em> view.invalidate();

 <strong>return true</strong>;

 <strong>case </strong>DragEvent.<strong><em>ACTION_DRAG_LOCATION</em></strong>:

 <em><strong><span style="color: #008000;">// Ignore the event</span></strong>
</em> <strong>return true</strong>;

 <strong>case </strong>DragEvent.<strong><em>ACTION_DRAG_EXITED</em></strong>:

<span style="color: #008000;"><strong> <em>// Re-sets the color tint to blue, if you had set the BLUE color or any color in ACTION_DRAG_STARTED. Returns true; the return value is ignored.
</em></strong></span><em>
</em><span style="color: #0000ff;"><strong><em> // view.getBackground().setColorFilter(Color.BLUE, PorterDuff.Mode.SRC_IN);
</em></strong></span><em>
</em><span style="color: #008000;"><strong><em> //If u had not provided any color in ACTION_DRAG_STARTED then clear color filter.
</em></strong></span> view.getBackground().clearColorFilter();

<strong><span style="color: #008000;"> <em>// Invalidate the view to force a redraw in the new tint
</em></span></strong> view.invalidate();

 <strong>return true</strong>;

 <strong>case </strong>DragEvent.<strong><em>ACTION_DROP</em></strong>:

 <em><strong><span style="color: #008000;">// Gets the item containing the dragged data</span></strong>
</em> ClipData.Item item = dragEvent.getClipData().getItemAt(0);

 <em><strong><span style="color: #008000;">// Gets the text data from the item.</span></strong>
</em> String dragData = item.getText().toString();

 <em><strong><span style="color: #008000;">// Displays a message containing the dragged data.</span></strong>
</em> Toast.<em>makeText</em>(<strong>this</strong>, <strong>"Dragged data is " </strong>+ dragData, Toast.<strong><em>LENGTH_SHORT</em></strong>).show();

 <em><strong><span style="color: #008000;">// Turns off any color tints</span></strong>
</em> view.getBackground().clearColorFilter();

 <em><strong><span style="color: #008000;">// Invalidates the view to force a redraw</span></strong>
</em> view.invalidate();

 <em><strong><span style="color: #008000;">//get dragged view</span></strong>
</em> View v = (View) dragEvent.getLocalState();
 ViewGroup owner = (ViewGroup) v.getParent();
 owner.removeView(v); <em><span style="color: #008000;"><strong>//remove the dragged view</strong></span>
</em> LinearLayout container = (LinearLayout) view; <em><strong><span style="color: #008000;">//caste the view into LinearLayout as our drag acceptable layout is LinearLayout</span></strong>
</em> container.addView(v); <em><strong><span style="color: #008000;">//Add the dragged view</span></strong>
</em> v.setVisibility(View.<strong><em>VISIBLE</em></strong>);<em><strong><span style="color: #008000;">//finally set Visibility to VISIBLE</span></strong>

</em><strong><span style="color: #008000;"><em> // Returns true. DragEvent.getResult() will return true.
</em></span> return true</strong>;

 <strong>case </strong>DragEvent.<strong><em>ACTION_DRAG_ENDED</em></strong>:

 <em><strong><span style="color: #008000;">// Turns off any color tinting</span></strong>
</em> view.getBackground().clearColorFilter();

<strong><span style="color: #008000;"> <em>// Invalidates the view to force a redraw
</em></span></strong> view.invalidate();

<strong><span style="color: #008000;"> <em>// invoke getResult(), and displays what happened.
</em></span> if </strong>(dragEvent.getResult())
 Toast.<em>makeText</em>(<strong>this</strong>, <strong>"The drop was handled."</strong>, Toast.<strong><em>LENGTH_SHORT</em></strong>).show();

 <strong>else
</strong> Toast.<em>makeText</em>(<strong>this</strong>, <strong>"The drop didn't work."</strong>, Toast.<strong><em>LENGTH_SHORT</em></strong>).show();


 <em><strong><span style="color: #008000;">// returns true; the value is ignored.</span></strong>
</em> <strong>return true</strong>;

 <em><strong><span style="color: #008000;">// An unknown action type was received.</span></strong>
</em> <strong>default</strong>:
 Log.<em>e</em>(<strong>"DragDrop Example"</strong>, <strong>"Unknown action type received by OnDragListener."</strong>);
 <strong>break</strong>;
 }
 <strong>return false</strong>;
 }


 @Override
 <strong>public boolean </strong>onLongClick(View view) {

<strong><span style="color: #008000;"> <em>// Create a new ClipData.Item from the tag
</em></span></strong> ClipData.Item item = <strong>new </strong>ClipData.Item((CharSequence) view.getTag());

 String[] mimeTypes = {ClipDescription.<strong><em>MIMETYPE_TEXT_PLAIN</em></strong>};

 <span style="color: #008000;"><strong><em>// 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
</em></strong></span><em><span style="color: #008000;"><strong> // ClipData, and set its MIME type entry to "text/plain"</strong></span>
</em> ClipData data = <strong>new </strong>ClipData(view.getTag().toString(), mimeTypes, item);

 <em><strong><span style="color: #008000;">// Instantiates the drag shadow builder.</span></strong>
</em> View.DragShadowBuilder shadowBuilder = <strong>new </strong>View.DragShadowBuilder(view);

 <em><span style="color: #008000;"><strong>// Starts the drag</strong></span>
</em> view.startDrag(data <em><strong><span style="color: #008000;">//data to be dragged</span></strong>
</em> , shadowBuilder <em><strong><span style="color: #008000;">//drag shadow</span></strong>
</em> , view <em><strong><span style="color: #008000;">//local data about the drag and drop operation</span></strong>
</em> , 0 <em><strong><span style="color: #008000;">//flags (not currently used, set to 0)</span></strong>
</em> );

<strong><span style="color: #008000;"> <em>//Set view visibility to INVISIBLE as we are going to drag the view
</em></span></strong> view.setVisibility(View.<strong><em>INVISIBLE</em></strong>);

 <strong>return true</strong>;
 }
}</pre>



<p>3. When you run the app it will look like this as shown below:</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><img src="https://c1ctech.com/wp-content/uploads/2020/12/Screenshot_1608202010.png" alt="" class="wp-image-2300" width="331" height="588"/></figure></div>


