Implement drag-and-drop location switching for ListItem items in custom ListView (with source code)

Source: Internet
Author: User

Preface
In the previous article, we implemented the listitem layout through the layout pump, and then implemented the ListView for contacts. What we need to do in this chapter is to drag and drop the items of the ListView, this chapter is based on the previous blog. The previous blog: Custom Adapter and LayoutInflater capture the layout template to edit each item.

Implementation

Description
First, we can see that the above figure is implemented. After dragging, the data items are switched.

Function Analysis
We can see that this effect is a function of dragging the position of the items in the ListView, in terms of Layout, LayoutInflater is used to get different Layout templates based on the Layout pump and then return the view. The layout knowledge is described in detail in the previous article. It is explained at the beginning of the article. OK. Let's analyze the implementation of this drag effect, the following article will show the code of each method in the order of method execution. Then, the functions of each method are analyzed in sequence.

Method execution sequence
[DragView]-> [initialize ListViewContext and the minimum distance variable that triggers the move event]
[OnInterceptTouchEvent]-> [initialize the variable to be dragged]
[StartDrag]-> [prepare the dragged image, window, and other variables]
[StopDrag]-> [determine to reset the dragged image]
[StartDrag]-> [prepare the dragged image, window, and other variables]
[OnTouchEvent]-> [Determine the click event, perform different operations based on the action, or re-draw the Move effect, or Stop the drag. Exchange data, that is, the following two methods]
[OnDrag]-> [Rolling Action]
[OnDrop]-> [implement data item location SWITCH]
Note:
The execution sequence of the above methods is only rough logic. In this case, other methods are called in the judgment and method, so the method is called multiple times. Let's take a look at the general functions of the method, it should be noted that the onTouchEvent we override must constantly listen to our buttons. If it is for moving, it will always call the onDrag method to implement the rolling action, here I did a test and showed you the printed log as follows:

We can see that the move log has been executed multiple times. It indicates that we have been executing this method while dragging. Next, I will give you a custom ListView Code. The Code has a large amount of comments and high readability. We recommend that you refer to the running sequence of the methods mentioned above for understanding. Finally, I will provide the running source code.Copy codeThe Code is as follows: package com. example. draglistview;
Import com. example. draglistview. MainActivity. DragListAdapter;
Import android. content. Context;
Import android. graphics. Bitmap;
Import android. graphics. BitmapFactory;
Import android. graphics. PixelFormat;
Import android. util. AttributeSet;
Import android. util. Log;
Import android. view. Gravity;
Import android. view. MotionEvent;
Import android. view. View;
Import android. view. ViewConfiguration;
Import android. view. ViewGroup;
Import android. view. WindowManager;
Import android. widget. AdapterView;
Import android. widget. ImageView;
Import android. widget. ListView;
Import android. widget. Toast;
Public class DragView extends ListView {
Private ImageView imageView; // the image to be dragged
Private int scaledTouchSlop; // determines the drag distance.

Private int dragSrcPosition; // the original position of the finger when the touch event is touched.
Private int dragPosition; // The position when the finger is dragging the list item.

Private int dragPoint; // The Position of the finger clicking position in the item of the current data item, which is only Y coordinate.
Private int dragOffset; // the position of the current listview in the screen, which is only Y coordinate.

Private int upScrollBounce; // sliding up boce
Private int downScrollBounce; // the border that slides down when dragging

Private WindowManager windowManager = null; // window management class
// Window parameter class
Private WindowManager. LayoutParams layoutParams = null;

// Note that if the View is registered and used in Layout xml, the following structure must be used for initialization.
Public DragView (Context context, AttributeSet attrs ){
Super (context, attrs );
// Minimum distance for triggering a mobile event
ScaledTouchSlop = ViewConfiguration. get (context). getScaledTouchSlop ();
}
// Rewrite to absListView
@ Override
Public boolean onInterceptTouchEvent (MotionEvent ev ){

If (ev. getAction () = MotionEvent. ACTION_DOWN ){
// Obtain the x and y coordinates of the touch event. The coordinates are relative to the position in the upper left corner of the component.
Int x = (int) ev. getX ();
Int y = (int) ev. getY ();
// Assign a value to the start coordinate when the finger clicks
DragSrcPosition = dragPosition = this. pointToPosition (x, y );
// If you click outside the list, it is not allowed.
If (dragPosition = AdapterView. INVALID_POSITION ){
// Directly execute the parent class without any operation
Return super. onInterceptTouchEvent (ev );
}

/***
* Lock the list item of the finger touch,
* The parameter is the touch coordinate of the screen minus the coordinate in the upper left corner of the listview.
* Here, the getChildAt method parameter is 00 relative to the coordinate in the upper left corner of the component.
* The following parameter algorithms are available:
*/
ViewGroup itemView = (ViewGroup) this. getChildAt (dragPosition-this.getFirstVisiblePosition ());
/****
* Note: getX Y indicates the distance between the touch point and the upper left corner of the component.
* GetRawX and Y are the distance between the touch point and the upper left corner of the screen.
* Reference http://blog.csdn.net/love_world_/article/details/8164293
*/
// Distance between the touch point view and the top coordinate of the childitem
DragPoint = y-itemView.getTop ();
// Subtract Y from the upper left corner of the screen from Y from the upper left corner of the widget.
// View + title bar + Y of the status bar at the top of the component
DragOffset = (int) (ev. getRawY ()-y );

// Get the dragged imageview object
View drager = itemView. findViewById (R. id. imageView1 );

// Determine whether the condition is that the drag touch image is null or the touch position.
If (drager! = Null & x> drager. getLeft ()-20 ){

// Determine the value of sliding up and sliding down
UpScrollBounce = Math. min (y-scaledTouchSlop, getHeight ()/3 );
DownScrollBounce = Math. max (y + scaledTouchSlop, getHeight () * 2/3 );
// Enable drawing Cache
ItemView. setDrawingCacheEnabled (true );
// Obtain the corresponding Bitmap Based on the image Cache
Bitmap bm = Bitmap. createBitmap (itemView. getDrawingCache ());
StartDrag (bm, y );
}
Return false;
}
Return super. onInterceptTouchEvent (ev );
}

// Override OnTouchEvent and touch event
@ Override
Public boolean onTouchEvent (MotionEvent ev ){
If (imageView! = Null & dragPosition! = INVALID_POSITION ){
Int currentAction = ev. getAction ();

Switch (currentAction ){
Case MotionEvent. ACTION_UP:
Int upY = (int) ev. getY ();
// Some other operations
StopDrag ();
OnDrop (upY );
Break;
Case MotionEvent. ACTION_MOVE:
Log. v ("move", "move ---------");
Int moveY = (int) ev. getY ();
OnDrag (moveY );
Break;
Default:
Break;
}
Return true;
}
// Determines the selected Effect
Return super. onTouchEvent (ev );
}

/****
* Ready to drag, initialize the image when dragging, and some window parameters
* @ Param bm drag the cached bitmap
* @ Param y: Position of the touch before dragging
*/
Public void startDrag (Bitmap bm, int y ){
StopDrag ();
LayoutParams = new WindowManager. LayoutParams ();
// Set the gravity
LayoutParams. gravity = Gravity. TOP;
// The horizontal axis coordinates remain unchanged.
LayoutParams. x = 0;
/**
*
* Y axis coordinates indicate that the y-touch point in the view relative to the upper left corner of the view is Y in the list item.
* + View relative to Y in the upper left corner of the screen, =
* Position of the view relative to the upper left corner of the screen
*/
LayoutParams. y = y-dragPoint + dragOffset;
/****
* The width and height are both wrapContent.
*/
LayoutParams. width = WindowManager. LayoutParams. WRAP_CONTENT;
LayoutParams. height = WindowManager. LayoutParams. WRAP_CONTENT;

/****
* Set some flags parameters for this layout Parameter
*/
LayoutParams. flags = WindowManager. LayoutParams. FLAG_NOT_FOCUSABLE
| WindowManager. LayoutParams. FLAG_NOT_TOUCHABLE
| WindowManager. LayoutParams. FLAG_KEEP_SCREEN_ON
| WindowManager. LayoutParams. FLAG_LAYOUT_IN_SCREEN;
// Set the window to a translucent format
LayoutParams. format = PixelFormat. TRANSLUCENT;
// Set no animation
LayoutParams. windowAnimations = 0;

// Configure an image ImageView
ImageView imageViewForDragAni = new ImageView (getContext ());
ImageViewForDragAni. setImageBitmap (bm );
// Configure the windowManager
WindowManager = (WindowManager) this. getContext (). getSystemService ("window ");
WindowManager. addView (imageViewForDragAni, layoutParams );
ImageView = imageViewForDragAni;
}

/***
* Stop dragging and remove the image when dragging
*/
Public void stopDrag (){
If (imageView! = Null ){
WindowManager. removeView (imageView );
ImageView = null;
}
}

/****
* Drag Method
* @ Param y
*/
Public void onDrag (int y ){

If (imageView! = Null ){
// Transparency
LayoutParams. alpha = 0.8f;
LayoutParams. y = y-this.dragPoint + this. dragOffset;
WindowManager. updateViewLayout (imageView, layoutParams );
}

// Avoid dragging to the split line and return-1
Int tempPosition = this. pointToPosition (0, y );
If (tempPosition! = This. INVALID_POSITION ){
This. dragPosition = tempPosition;
}

Int scrollHeight = 0;
If (y <upScrollBounce ){
ScrollHeight = 8; // defines 8 pixels to scroll up. If you can scroll up
} Else if (y> downScrollBounce ){
ScrollHeight =-8; // defines 8 pixels to scroll down. If you can scroll up
}

If (scrollHeight! = 0 ){
// The Real rolling method setSelectionFromTop ()
SetSelectionFromTop (dragPosition, getChildAt (dragPosition-getFirstVisiblePosition (). getTop () + scrollHeight );
}
}

/***
* When dragging and dropping
* Param: y
*/
Public void onDrop (int y ){
Int tempPosition = this. pointToPosition (0, y );
If (tempPosition! = This. INVALID_POSITION ){
This. dragPosition = tempPosition;
}

// Process beyond the boundary
If (y <getChildAt (1). getTop ()){
// Exceeds the upper boundary
DragPosition = 1;
} Else if (y> getChildAt (getChildCount ()-1). getBottom ()){
// Exceeds the bottom boundary
DragPosition = getAdapter (). getCount ()-1;
//
}
// Data exchange
If (dragPosition> 0 & dragPosition <getAdapter (). getCount ()){
@ SuppressWarnings ("unchecked ")
DragListAdapter adapter = (DragListAdapter) getAdapter ();
// The item at the original position
String dragItem = adapter. getItem (dragSrcPosition );
Adapter. remove (dragItem );
Adapter. insert (dragItem, dragPosition );
Toast. makeText (getContext (), adapter. getList (). toString (), Toast. LENGTH_SHORT). show ();
}
}
}

Words written below
The above is the source code of the custom ListView. Of course there are still some unprovided code. Including MainActivity and three Layout xml files. [Relatively simple] If you understand [or have some questions] The above code, you can download my source code to check related APIs and cases to learn and make progress, success!

Source code download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.