GridView Basics
a new Hellogridview project.
Modify the Main.xml code as follows:
<?xml version= "1.0" encoding= "Utf-8"?> <gridview xmlns:android=
"http://schemas.android.com/apk/" Res/android "
android:id=" @+id/gridview "
android:layout_width=" fill_parent "
android:layout_height=" Fill_parent "
android:columnwidth=" 90DP "
android:numcolumns=" Auto_fit "
android:horizontalspacing=" 10DP "
android:verticalspacing=" 10DP "
android:stretchmode=" columnWidth "
android:gravity=" center " >
</GridView>
It's simple, it's a gridview. Set the column width to 90DP so that when our numcolumns is set to Auto_fit, Android automatically calculates the size of our phone screen to determine how many elements each row will display. It is very convenient. Android:horizontalspacing defines the interval between columns, android:verticalspacing defines the spacing between rows. Android:stretchmode set to ColumnWidth means that it is automatically scaled according to the column width.
Modify our activity Hellogridview as follows:
The public class Hellogridview extends activity {/** called the ' when ' is the ' The activity ' is a-a-created
Ted void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
GridView gridview= (GridView) Findviewbyid (R.id.gridview);
Gridview.setadapter (This) (new Imageadapter); Click the response gridview.setonitemclicklistener of the GridView element (new Onitemclicklistener () {@Override public void O
Nitemclick (adapterview<?> Parent, view view, int position, long ID) {//pop-up click of the GridView element position
Toast.maketext (Hellogridview.this,mthumbids[position], toast.length_short). Show ();
}
});
Private class Imageadapter extends baseadapter{private context mcontext;
Public Imageadapter {this.mcontext=context;
@Override public int GetCount () {return mthumbids.length; } @Override Public ObjeCT getitem (int position) {return mthumbids[position];
@Override public long getitemid (int position) {//TODO auto-generated method stub return 0; @Override public View getview (int position, View Convertview, ViewGroup parent) {//define a ImageView
, shown in the GridView ImageView ImageView;
if (convertview==null) {imageview=new imageview (mcontext);
Imageview.setlayoutparams (New Gridview.layoutparams (85, 85));
Imageview.setscaletype (ImageView.ScaleType.CENTER_CROP);
Imageview.setpadding (8, 8, 8, 8);
}else{ImageView = (imageview) Convertview;
} imageview.setimageresource (Mthumbids[position]);
return ImageView;
}//Show pictures private integer[] Mthumbids = {r.drawable.sample_2, r.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, r.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7, R.drawable.sample_0, R.drawable.sample_1, R.drawable.sample
_2, R.drawable.sample_3, R.drawable.sample_4, R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7
};
}
Here we are also using custom adapter, which can be explained in the custom adapter of the previous section. Show some pictures, and then click a picture to show the location of the picture.
Run the program, the effect diagram is as follows:
Long Press drag and item real time
the GridView is primarily to display grid controls, which are common in the development of Android, and are more complex to use than Textview,button these controls. Today to bring you a long press the GridView item, and then drag and drop the other item above, so that the GridView item Exchange, the more typical is our launcher, the Internet has a lot about the GridView drag demo, But most of them are the same, and there are some bugs, and most of them are click on the GridView item and then drag, or the item does not exchange in real time, today to give you more detailed introduction of the GridView drag, and will do a more perfect demo, we are more easily accepted, Perhaps a lot of people hear this feeling to realize very complicated, turn off this article, in fact, tell you, as long as you know the idea of the feeling is not complicated, do not believe you can continue to look down, first of all, or to talk about the realization of the idea of the
according to the fingers of the Y coordinates to get the item we clicked on the GridView
when the finger is pressed, use handler and runnable to implement a timer, if the timer is 1000 milliseconds, within 1000 milliseconds, if the finger is lifted to remove the timer, Without lifting and clicking on the area of the GridView item, we have pressed the GridView item
If we have pressed the item for a long time, hide the item. Then use WindowManager to add a mirror of the item on the screen instead of just the hidden item
When our fingers are moving on the screen, update the position of the item mirror, and then on the x that we moved, The coordinates of Y to get where to move to the GridView
to the GridView item too much, maybe one screen is not finished, we drag the item mirror to the bottom of the screen, to trigger the GridView to scroll, and, similarly, When we drag the item mirror to the screen, triggering the GridView scroll down
GridView Exchange data, refresh the interface, remove the image of item
Read the above ideas you are not found some feeling, the heart itch to try it, okay, Then we will follow the idea to achieve the drag of the GridView, a new project is called Draggridview
Create a new class Draggridview inherit the GridView, first look at the Draggridview code, Then you'll explain it in terms of your code
Package Com.example.draggridview;
Import android.app.Activity;
Import Android.content.Context;
Import Android.graphics.Bitmap;
Import Android.graphics.PixelFormat;
Import Android.graphics.Rect;
Import Android.os.Handler;
Import Android.os.Vibrator;
Import Android.util.AttributeSet;
Import android.view.Gravity;
Import android.view.MotionEvent;
Import Android.view.View;
Import Android.view.WindowManager;
Import Android.widget.AdapterView;
Import Android.widget.GridView;
Import Android.widget.ImageView; The public class Draggridview extends gridview{/** * Draggridview Item length In response time, default is 1000 milliseconds, you can also set the * * Private lon
G Dragresponsems = 1000;
/** * Whether can drag and drop, the default can not be * * Private Boolean Isdrag = false;
private int mdownx;
private int mdowny;
private int MoveX;
private int Movey;
/** * is dragging the position * * private int mdragposition;
/** * Just start dragging the item corresponding to view/private view Mstartdragitemview = null; /**
* Used to drag the mirror, here directly with a ImageView/private ImageView Mdragimageview;
/** * Vibration Device/private vibrator mvibrator;
Private WindowManager Mwindowmanager;
/** * Item Mirror Layout parameters * * Private windowmanager.layoutparams mwindowlayoutparams;
/** * We drag the item corresponding to the BITMAP * * Private Bitmap Mdragbitmap;
/** * Press the point to the top edge of the item on the distance * * private int mpoint2itemtop;
/** * Press the point to the left edge of the item on the distance * * private int mpoint2itemleft;
/** * Draggridview The offset from the top of the screen * * private int moffset2top;
/** * Draggridview The offset from the left side of the screen * * private int moffset2left;
/** * The height of the status bar * * private int mstatusheight;
/** * Draggridview automatically scroll down the boundary value * * Private int mdownscrollborder;
/** * Draggridview automatic up-Scrolling boundary value * * Private int mupscrollborder;
/** * Draggridview Automatic scrolling speed * * private static final int speed = 20; /** * Item Change Callback interface * * Private Onchanagelistener Onchanagelistener;
Public Draggridview {This (context, NULL);
Public Draggridview (context, AttributeSet attrs) {This (context, attrs, 0);
Public Draggridview (context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);
Mvibrator = (Vibrator) context.getsystemservice (Context.vibrator_service);
Mwindowmanager = (WindowManager) context.getsystemservice (Context.window_service); Mstatusheight = getstatusheight (context);
Gets the height of the status bar} private Handler Mhandler = new Handler (); Used to handle Runnable private Runnable mlongclickrunnable = new Runnable () {@Override public void run () {Isdrag = true;//settings can be dragged mvibrator.vibrate (50);//Shake the Mstartdragitemview.setvisibility (View.invisi
BLE);//Hide the item///According to our pressed point display item mirror CreateDragImage (Mdragbitmap, Mdownx, Mdowny);
}
};
/** * Set Callback interface * @param onchanagelistener */public void Setonchangelistener (Onchanagelistener Onchanageli
Stener) {this.onchanagelistener = Onchanagelistener; /** * Sets the number of milliseconds that the response is dragged, by default 1000 milliseconds * @param dragresponsems/public void Setdragresponsems (Long dragrespo
Nsems) {this.dragresponsems = Dragresponsems; @Override public boolean dispatchtouchevent (motionevent ev) {switch (ev.getaction ()) {case Motionevent .
ACTION_DOWN:MDOWNX = (int) ev.getx ();
Mdowny = (int) ev.gety ();
To obtain the position mdragposition = Pointtoposition (Mdownx, Mdowny) of the item clicked according to the x,y coordinates;
if (mdragposition = = adapterview.invalid_position) {return super.dispatchtouchevent (EV); ///Use handler delay Dragresponsems execution mlongclickrunnable mhandler.postdelayed (mlongclickrunnable, Dragrespo
Nsems); Get the View Mstartdragitemview = Getchild of the item according to positionAt (Mdragposition-getfirstvisibleposition ());
Below these several distances everybody may refer to my blog above diagram to understand under Mpoint2itemtop = Mdowny-mstartdragitemview.gettop ();
Mpoint2itemleft = Mdownx-mstartdragitemview.getleft ();
Moffset2top = (int) (Ev.getrawy ()-mdowny);
Moffset2left = (int) (EV.GETRAWX ()-MDOWNX);
Gets the offset that Draggridview automatically scrolls up, less than this value, Draggridview scroll down mdownscrollborder = GetHeight ()/4;
Gets the offset that the draggridview automatically scrolls down, greater than this value, Draggridview scroll up mupscrollborder = GetHeight () * 3/4;
Open Mdragitemview Drawing Cache mstartdragitemview.setdrawingcacheenabled (TRUE);
Gets the Bitmap object mdragbitmap = Bitmap.createbitmap (Mstartdragitemview.getdrawingcache ()) of the Mdragitemview in the cache;
This step is critical, freeing up the drawing cache to avoid duplicate mirror Mstartdragitemview.destroydrawingcache ();
Break
Case MotionEvent.ACTION_MOVE:int MoveX = (int) ev.getx ();
int movey = (int) ev.gety (); //If we move above the item, we do not remove the mrunnable if (!istouchinitem (Mstartdragitemview, MoveX, Movey)) {Mhandle
R.removecallbacks (mlongclickrunnable);
} break;
Case MotionEvent.ACTION_UP:mHandler.removeCallbacks (mlongclickrunnable);
Mhandler.removecallbacks (mscrollrunnable);
Break
return super.dispatchtouchevent (EV);
}
/** * Click on the GridView Item * @param itemview * @param x * @param y * @return/private bool
Ean Istouchinitem (View dragview, int x, int y) {if (Dragview = null) {return false;
int leftoffset = Dragview.getleft ();
int topoffset = Dragview.gettop ();
if (x < LeftOffset | | | | x > LeftOffset + dragview.getwidth ()) {return false;
} if (Y < Topoffset | | y > topoffset + dragview.getheight ()) {return false;
return true; @Override public boolean ontouchevent (motionevent ev) {if isdrag && mdragimageview!= null
{switch (ev.getaction ()) {Case MotionEvent.ACTION_MOVE:moveX = (int) ev.getx ();
Movey = (int) ev.gety ();
Drag the item Ondragitem (MoveX, Movey);
Break
Case MotionEvent.ACTION_UP:onStopDrag ();
Isdrag = false;
Break
return true;return super.ontouchevent (EV);
}
/** * Create a dragged mirror * @param bitmap * @param downx * The point relative to the parent control's x coordinate * @param downY * The point relative to the parent control X-coordinate */private void CreateDragImage (Bitmap Bitmap, int downx, int downY) {mwindowlayoutparams = new windowma Nager.
Layoutparams (); Mwindowlayoutparams.format = pixelformat.translucent; Other places outside the picture transparent mwindowlayoutparams.gravity = Gravity.top |
Gravity.left;
Mwindowlayoutparams.x = Downx-mpoint2itemleft + moffset2left;
Mwindowlayoutparams.y = Downy-mpoint2itemtop + moffset2top-mstatusheight; Mwindowlayoutparams.alpha = 0.55f;
Transparency mwindowlayoutparams.width = WindowManager.LayoutParams.WRAP_CONTENT;
Mwindowlayoutparams.height = WindowManager.LayoutParams.WRAP_CONTENT; Mwindowlayoutparams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Mdragimageview = new ImageView (GetContext ());
Mdragimageview.setimagebitmap (bitmap); Mwindowmanager.addview (Mdragimageview, mwindowlayoutparams);
}
/**
* Move the drag mirror from the interface * *
private void Removedragimage () {
if (Mdragimageview!= null) {
Mwindowmanager.removeview (Mdragimageview);
Mdragimageview = null;
}
}
/**
* Drag the item, in which the item mirrors the location of the update, the exchange of the item and the GridView self rolling
* @param x
* @param y * *
Private void Ondragitem (int moveX, int movey) {
mwindowlayoutparams.x = movex-mpoint2itemleft + moffset2left;
Mwindowlayoutparams.y = Movey-mpoint2itemtop + moffset2top-mstatusheight;
Mwindowmanager.updateviewlayout (Mdragimageview, mwindowlayoutparams); Update the location of the Mirror
Onswapitem (MoveX, Movey);
GridView Automatic scrolling
mhandler.post (mscrollrunnable);
}
/**
* When the value of the Movey is greater than the bounding value of the scroll up, the trigger is automatically scrolled up
* When the value of the Movey is less than the value of the downward scrolling boundary, the GridView automatically scrolls down
* Otherwise no scrolling
Private Runnable mscrollrunnable = new Runnable () {
@Override public
void Run () {
int scrolly;
if (Movey > Mupscrollborder) {
scrolly = speed;
Mhandler.postdelayed (mscrollrunnable);
else if (Movey < Mdownscrollborder) {
scrolly =-speed;
Mhandler.postdelayed (mscrollrunnable);
else{
scrolly = 0;
Mhandler.removecallbacks (mscrollrunnable);
}
When our fingers reach the GridView up or down offset, we may not have moved our fingers, but draggridview in the automatic scrolling
//So we call the next Onswapitem () method here to exchange the item
Onswapitem (MoveX, Movey);
Smoothscrollby (scrolly, ten);
}
;
/**
* Exchange Item and control the display and hidden effects between item
* @param moveX
* @param movey
/private void Onswapitem (int moveX , int movey) {
//get the position
int tempposition = pointtoposition (MoveX) of the item that our fingers move to;
If Tempposition has changed and tempposition is not equal to-1, then Exchange
if (tempposition!= mdragposition && tempposition!= Adapterview.invalid_position) {
if (Onchanagelistener!= null) {
Onchanagelistener.onchange (mdragposition , tempposition);
}
Getchildat (Tempposition-getfirstvisibleposition ()). Setvisibility (view.invisible);//Drag to new item, new item hidden away
Getchildat (Mdragposition-getfirstvisibleposition ()). Setvisibility (view.visible);//previous item displayed
Mdragposition = tempposition;
}
/**
* Stop dragging us to display the previously hidden item and remove the mirror from *
*
private void Onstopdrag () {
View view = Getchildat (mdragposition -Getfirstvisibleposition ());
if (view!= null) {
view.setvisibility (view.visible);
}
((Dragadapter) This.getadapter ()). Setitemhide ( -1);
Removedragimage ();
}
/**
* Gets the height of the status bar
* @param context
* @return
/private static int Getstatusheight (context) { C6/>int statusheight = 0;
Rect localrect = new Rect ();
(activity). GetWindow (). Getdecorview (). Getwindowvisibledisplayframe (localrect);
Statusheight = Localrect.top;
if (0 = = statusheight) {
class<?> localclass;
try {
Localclass = Class.forName ("Com.android.internal.r$dimen");
Object localobject = Localclass.newinstance ();
int i5 = integer.parseint (Localclass.getfield ("Status_bar_height"). Get (Localobject). toString ());
Statusheight = Context.getresources (). Getdimensionpixelsize (i5);
catch (Exception e) {
e.printstacktrace ();
}
}
return statusheight;
}
/** * * * *
@author xiaanming * */public
interface onchanagelistener{
/**
* When the item is exchanged for the callback method, we only need to implement the data exchange in the method *
@param form
* start position
* @param to
* Drag to position/public
void onChange (int form, int to);
}
First look at the Draggridview event distribution method, do not understand the Android event distribution can go first to understand, the Android event distribution for the custom control is very important, simply, when we click on the Draggridview item, The Dispatchtouchevent () method is used to distribute the event, so we want to rewrite the Dispatchtouchevent () method according to the pointtoposition when the finger is pressed () method to get the position of the item we pressed, according to the Getchildat () method to get the view corresponding to the position, and to open a long press timer with a default time of 1000 milliseconds. If the finger is raised in 1000 milliseconds or the finger slides out of the item on the screen, cancel the long press timer, otherwise it will be able to drag, the phone friendly vibration, hide our long press item, screen call CreateDragImage () method to create a mirror image of the item we have long pressed on, the image of the item is created using the WindowManager class, which creates a form that is displayed above the activity,
Before we begin to understand these distances, we should first know the difference between getrawx (), Getrawy () and Getx (), GetY (), GETRAWX (), Getrawy () is the distance from the origin of the screen, and Getx (), GetY () is relative to the top left of the control of the distance, in order to facilitate the understanding that I use word simple to draw the following picture, painting is not good, we will look at the red box for our GridView
- Mpoint2itemtop Finger Press the point to the top edge of the item distance, as shown above on line Line 1
- Mpoint2itemleft Finger Press the point to the left edge of the item, as shown on line Line 2
- The distance from the top edge of the Moffset2top Draggridview to the top edge of the screen, as shown on line Line 3 above, this distance wraps the status bar, the title bar, or some of the height of the layout above the Draggridview, this is very important. Our realistic item mirroring requires
- Moffset2left Draggridview's left margin to the left edge of the screen, such as the Line 4 line above, I this demo this distance is 0, because I set the width of Draggridview to fill the screen, But we have to consider the case where the Draggridview with the left edge of the screen or other layouts on the left side
- Mdownscrollborder This distance means that when Draggridview item is too much, the phone screen display is not complete, we drag the item mirror to this height, Draggridview automatically downward scrolling, as shown on line Line 5
- Mupscrollborder this is the opposite of Mdownscrollborder, when we are larger than this, Draggridview automatically scrolls upwards, as shown on line Line 6 above.
Understanding these six distances, let's take a look at the method of creating the item mirror inside, the other I don't say much, First set the format to Pixelformat.translucent, which means that in addition to showing the picture and other places of the text as transparent, after that is the x,y of these two distances, the calculation is the upper-left corner of the item coordinates, understanding the above six distance we can easily draw X, Y coordinates, but you will find the coordinates of y minus the height of the status bar, which we need to pay attention to, and we need to get the item to draw the cached bitmap object, and then set the bitmap to a imageview above, why do this? If you call the AddView () method to add the item directly to the WindowManager, there will be an exception, because the item already has its own parent container draggridview, All of us here use a imageview instead of item to add to WindowManager inside
The above has completed the start to drag the preparation work, in order to drag the mirror we also need to rewrite the Ontouchevent () method, get the moving x,y coordinates, using the WindowManager Updateviewlayout method can drag the mirror, When you drag the mirror in order to have a better user experience, we have to do the real time exchange effect of the item, we use the finger to move the x,y coordinates, using pointtoposition () to get drag and drop to the position, and then the previous item display, Drag and drop to the item to hide, this completes the item in the interface above the exchange, but the data exchange I did not do here, so I provided the callback interface Onchanagelistener, we only need to implement the data exchange logic and then refresh Draggridview can, We also need to implement Draggridview automatic up or down scrolling, using handler and mscrollrunnable to use Smoothscrolltopositionfromtop () to achieve draggridview scrolling, The concrete realization everybody can see the code
The finger leaves the interface, the item's mirror is removed, and will drag and drop the item to show out, this way realizes the Girdview drag effect, next we use our custom to drag the GridView bar, first looks at the main interface layout, Only one of our custom Draggridview
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent " >
<com.example.draggridview.draggridview
android:id= "@+id/draggridview"
android:listselector = "@android: color/transparent"
android:layout_width= "match_parent"
android:layout_height= "Match_parent"
android:cachecolorhint= "@android: color/transparent"
android:verticalspacing= "10dip"
android: horizontalspacing= "10dip"
android:stretchmode= "columnWidth"
android:gravity= "center"
android: numcolumns= "3" >
</com.example.draggridview.DragGridView>
</RelativeLayout>
Next, let's look at the layout of Draggridview's item, a imageview underneath a TextView
<?xml version= "1.0" encoding= "Utf-8"?> <relativelayout xmlns:android=
"http://schemas.android.com/apk" /res/android "
android:layout_width=" fill_parent "
android:layout_height=" Wrap_content "
android: Background= "@android: Color/transparent" >
<imageview
android:id= "@+id/item_image"
android: Scaletype= "Centercrop"
android:layout_width= "wrap_content"
android:layout_height= "Wrap_content
" Android:layout_centerhorizontal= "true" >
</ImageView>
<textview
android:id= "@+id/ Item_text "
android:layout_width=" wrap_content "
android:layout_height=" Wrap_content "
android: layout_below= "@+id/item_image"
android:layout_centerhorizontal= "true" >
</TextView>
</RelativeLayout>
The layout's done, so let's take a look at the homepage mainactivity code.
Package Com.example.draggridview;
Import java.util.ArrayList;
Import java.util.Collections;
Import Java.util.HashMap;
Import java.util.List;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.widget.SimpleAdapter;
Import Com.example.draggridview.DragGridView.OnChanageListener; public class Mainactivity extends activity {private list<hashmap<string, object>> datasourcelist = new ARR
Aylist<hashmap<string, object>> ();
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Draggridview Mdraggridview = (draggridview) Findviewbyid (R.id.draggridview);
for (int i = 0; i < i++) {hashmap<string, object> itemhashmap = new hashmap<string, object> ();
Itemhashmap.put ("Item_image", R.drawable.com_tencent_open_notice_msg_icon_big); Itemhashmap.put ("Item_text", "drag" + integer.tostring (i));
Datasourcelist.add (ITEMHASHMAP); Final Simpleadapter msimpleadapter = new Simpleadapter (this, datasourcelist, R.layout.grid_item, n
EW string[] {"Item_image", "Item_text"}, new int[] {r.id.item_image, r.id.item_text});
Mdraggridview.setadapter (Msimpleadapter); Mdraggridview.setonchangelistener (New Onchanagelistener () {@Override public void onChange (int from,
int to) {hashmap<string, Object> temp = Datasourcelist.get (from);
Direct interaction Item//Datasourcelist.set (from, Datasourcelist.get (to));
Datasourcelist.set (To, temp);
Datasourcelist.set (To, temp); The processing here needs to be noted under if (from < to) {for (int i=from; i<to; i++) {Collections.swap (DataSource
List, I, i+1); }}else if (from > To) {for (int i=from; i>to; i--) {Collections.swap (datasourcelist, I, i-1);
} datasourcelist.set (to, temp);
Msimpleadapter.notifydatasetchanged ();
}
});
}
}
This inside the code is relatively simple, mainly talk about the next onchange () method, we want to set a Onchanagelistener callback interface for Mdraggridview, in the onchange () method to implement the exchange of data logic, The first argument from is where the item starts, the second parameter to the position that the item is dragged to, and the switch logic that I used at first is
hashmap<string, Object> temp = Datasourcelist.get (from);
Direct interaction Item
// Datasourcelist.set (from, Datasourcelist.get (to)); Datasourcelist.set (to, temp);
Direct exchange of the item data, and then saw the next NetEase news drag the GridView, he is not directly to achieve two item direct data exchange, so the data exchange logic to the following way
To put it simply, the exchange logic of data, for example, we drag position from 5 to 7, and the logic I annotate is to Exchange 5 and 7 directly, and the logic behind that is to move 6 of the position data to 5, move 7 to 6, and then 7 to show 5 6->5, 7->6 , 5->7 don't know whether you understand it or not.
Next we run the project, and before we run, we don't forget to add the Androidmanifest.xml to the <uses-permission android:name=. Android.permission.VIBRATE "/>
Well, today's explanation on this end, the effect is not bad, after reading this article you do not think the GridView drag is not so difficult to achieve it? Your mind is not also probably have their own a train of thought, suggested that everyone knock on their own to see, you can achieve the next ListView drag and drop implementation, ListView than the GridView simpler.