原文:http://mobile.tutsplus.com/tutorials/android/android-sdk-implementing-drag-and-drop-functionality/
The drag-and-drop facility on the Android SDK is an interaction feature many apps can benefit from and getting started is straightforward. In this tutorial, we will implement a basic drag-and-drop operation, making clear what additional options you have for your own projects!
The simple app we will build is going to allow the user to drag a list of items into order of preference. To the user it will appear that a visible UI item is being dragged to a different location. However, in reality the data associated with one Android View is being moved to another View. You are of course free to use the code in any app you are working on, but you will need to set a minimum SDK version of 11 to use the drag and drop processing.
Step 1: Create and Design the App
Create a new Android project in Eclipse. Enter the application settings of your choice, being sure to create a blank Activity and layout for it. Before we get started on the drag and drop functionality let’s get the layout sorted. We won’t be spending much time on the design so that we can focus on the functional part of the app.
In the layout file you specified when creating the project, enter a Linear Layout outline, replacing any existing content:
|
Inside the Linear Layout, begin with a small informative Text View:
<TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:paddingBottom="10dp" android:text="@string/intro"/> |
Add the specified string to your application “res/values/strings.xml” file:
|
While you have the strings file open, add the following three items:
|
These strings will be displayed on the items users will drag. There will be three slots for users to drag them onto, so add strings for labels on those next:
|
As you can imagine, in a real app these data items may be read in from a source or stored as XML resources, we are only including them “hard-coded” in this way for demonstration. Back in the layout file, add the first set of Text Views to represent the draggable items:
|
Each of these has an ID so that we can refer to it in the Activity class. We also use the strings we defined. We will create the background drawable soon. Next add the three Text Views onto which the draggable items can be dropped:
|
These also use IDs and string resources. In your application “res/drawables” folder, or folders, create the first background drawable we specified for the draggable Text Views. Select the drawables folder(s) and choose “File”, “New”, “File” – enter “option.xml” as the file name to match what we included in the layout. Insert the following code into the drawables file, defining the background shape:
|
Now create another drawables file, naming it “choice.xml”, this time and entering the following shape:
|
You can of course change any aspects of the user interface design to suit yourself.
Step 2: Setup the Activity
Let’s turn to the app functionality – open your Activity class. Your class will need the following imports, added before the opening class declaration line:
|
Inside the class declaration, before the onCreate method (which Eclipse should have automatically filled in for you), add some instance variables:
|
These will allow us to refer to the Text Views we created. Inside the onCreate method, after the existing code, retrieve these UI items as follows:
|
We use the ID attributes included in the layout XML.
Step 3: Create a Touch Listener Class
To use drag and drop within the Activity, we will create two inner classes. These classes will implement the Android interfaces required for dragging and dropping. Start by creating a class declaration outline for a Touch Listener, after the ActivityonCreate method:
|
This class will allow the app to detect users touching particular Views, treating a touch as the beginning of a drag operation. Inside the class, add theonTouch method:
|
Next check what Motion Event has triggered the onTouch method:
|
We are only interested in cases where the user has touched the View to drag it, so inside theif statement we will setup the drag operation. Before the “return true” statement, prepare the drag as follows:
|
This code is pretty standard, as we only need default behavior. However, you can amend this to tailor various aspects of the drag if you need to. You can alter the shadow builder code to set the appearance of the View during the drag. You can also alter the Clip Data if you need finer control over the data being dragged between Views. Now we can start the drag using these details:
|
If you only need a basic drag and drop process you do not need to worry too much about the details of the Touch Listener.
Step 4: Create a Drag Listener Class
We’ve created the listener class for dragging, now we need one for dropping. After the Touch Listener class, add a Drag Listener class declaration:
|
Add the onDrag method inside this new class:
|
This is where we respond to drag events. The Drag Listener can be used to detect and respond to various stages of the drag, each handled within a switch/case statement. Add it inside theonDrag method, before the return statement as follows:
|
Most of the drag events are not relevant to this app, however you can use them if you need more detailed control. We will add to theACTION_DROP section later.
Step 5: Add Listeners to the Text Views
We have Touch and Drag Listener classes defined, now we need to add instances of them to the Views we are dragging and dropping with. Back in theonCreate method, after the existing code, first add Touch Listeners to the three Text Views users will be able to drag:
|
Now add Drag Listeners to the three Views dragged items will be able to be dropped on:
|
We implement an instance of the Touch or Drop classes we created for each of the Text Views. Users will be able to drag any of the top three Text Views onto any of the bottom three.
Step 6: Handle Drops
Now we have the app setup for users to drag and drop items, we just have to define what should happen when an item is dropped on one of the bottom three Views. Back in your Drag Listener class, in theACTION_DROP case statement (before thebreak), first get a reference to the View being dropped:
|
This represents whichever one of the top three Text Views the user has dragged. Since they have successfully dropped it onto one of the bottom three Views, we can stop displaying it in its original position:
|
The onDrag method also receives a parameter representing the target View that the dragged item is being dropped on, so cast it as a Text View:
|
Let’s also cast the dropped View to a Text View:
|
We can now use these to update the text displayed in the bottom area:
|
Now the text from the dragged View is displayed within the View it was dropped onto. Let’s make it bold to distinguish it from the still vacant spots:
|
This is how the app appears after the user drags the “Apple” item to the bottom position in the list:
Step 7: Handle Duplicate Drops
The basic functionality is now complete, but let’s enhance this a little by handling cases in which the user drops more than one item onto the same slot.
We can keep a record of which item is currently dropped into each View in the bottom section using tags. When an item is dropped onto one of the target Views, we can set a tag representing the ID of the View being dropped. Each time we go to drop an item, we can first check whether the target View has a tag representing a View already dropped there. If there is one there, we can simply set its original View back to visible in the top section so that the user can drag it over again, since it is being replaced in the bottom list.
Still inside the ACTION_DROP section, check whether the current target View has a tag set:
|
We only want to reset one of the original Views back visible if there is a tag set:
|
Now we can update the tag to represent the new View data that has been dropped here:
|
This allows the user to change their mind by dropping items on top of existing items and still make a selection for the items previously dropped.
Conclusion
That’s our basic app complete. There are lots of ways in which you could enhance this app. For example, you could also allow users to drag Views from the bottom section after they have been dropped there, either to a different position in the bottom section or back to a position in the top section. To do this you would need to add both Touch and Drag Listeners to all Text Views in the top and bottom sections, so the logic is a little more complex. You could also enhance the app by reading the data in dynamically, or by creating custom designs for different stages of the drag and drop process. Whatever you do, make sure you test your drag and drop operations thoroughly.