利用android拖拽框架實現GirdView拖拽很簡單,按照幫助文檔實現便可。android
首先要有影像製造器View.DragShadowBuilder,而後在長按的點擊事件裏面生成item的影像,最後自定義一個實現了OnDragListener接口的監聽器,具體的識別,邏輯操做在監聽器裏面作。canvas
- public class MyDragShadowBuilder extends View.DragShadowBuilder {
- // 拖動陰影圖像,定義爲一個drawable
- private static Drawable shadow;
- // 定義myDragShadowBuilder的構造方法
- public MyDragShadowBuilder(View v) {
- // 保存傳給myDragShadowBuilder的View參數
- super(v);
- // 建立一個可拖動的圖像,用於填滿系統給出的Canvas
- shadow = new ColorDrawable(Color.LTGRAY);
- }
- // 定義回調方法,用於在Canvas上繪製拖動陰影,Canvas由系統根據onProvideShadowMetrics()傳入的尺寸參數創
- @Override
- public void onDrawShadow(Canvas canvas) {
- // 在系統傳入的Canvas上繪製ColorDrawable
- super.onDrawShadow(canvas);
- }
- // 定義一個回調方法,用於把拖動陰影的大小和觸摸點位置返回給系統
- @Override
- public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
- // 定義本地變量
- int width;
- int height;
- // 把陰影的寬度設爲原始View的一半
- width = getView().getWidth() / 2;
- // 把陰影的高度設爲原始View的一半
- height = getView().getHeight() / 2;
- // 拖動陰影是一個ColorDrawable對象。
- // 下面把它設爲與系統給出的Canvas同樣大小。這樣,拖動陰影將會填滿整個Canvas。
- shadow.setBounds(0, 0, width, height);
- // 設置長寬值,經過size參數返回給系統。
- shadowSize.set(width, height);
- // 把觸摸點的位置設爲拖動陰影的中心
- shadowTouchPoint.set(width / 2, height / 2);
- super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
- }
- }
- protected class myDragEventListener implements OnDragListener {
- // 這是系統向偵聽器發送拖動事件時將會調用的方法
- @Override
- public boolean onDrag(View v, DragEvent event) {
- // 定義一個變量,用於保存收到事件的action類型
- final int action = event.getAction();
- // 獲取本身的圖片名稱和位置
- for (int j = 0; j < 7; j++) {
- if (v.equals(grid.getChildAt(j))) {
- Log.d("GirdView的item", "這是第" + j + "個item");
- girdViewItemposition = j;
- girdViewItemName = list.get(j);
- }
- }
- // 獲取包含拖動數據的item
- // ClipData.Item item = event.getClipData().getItemAt(0);
- // 從數據項中獲取文本數據
- // String dragData_cc = (String) item.getText();
- Log.d(tag, "Dragged data is " + shadowName);
- // 處理全部須要的事件
- switch (action) {
- case DragEvent.ACTION_DRAG_STARTED:
- // 在應用程序調用 startDrag()並得到一個拖動陰影以後,視圖對象的拖動事件監聽器就會接收到這個事件類型的事件。
- // 肯定本View是否接受拖動數據
- if (event.getClipDescription().hasMimeType(
- ClipDescription.MIMETYPE_TEXT_PLAIN)) {
- Log.d(tag, "started:");
- return (true);
- } else {
- // 返回false。在本次拖放操做中,本View再也不會收到拖放事件,除非發出了ACTION_DRAG_ENDED。
- return (false);
- }
- case DragEvent.ACTION_DRAG_ENTERED:
- // 當拖動陰影剛剛進入視圖的邊界框範圍時,視圖的拖動事件監聽器就會接收到這個action類型的事件。
- // 這是當拖動陰影進入視圖的邊界框範圍時監聽器所接收到的第一個事件操做類型。若是監聽器還行繼續爲
- // 拖動陰影進入視圖邊界框範圍之這個動做接收拖動事件的話,那麼必須返回true給系統。
- Log.d(tag, "entered:影像進入第" + girdViewItemposition + "個GirdVie");
- Log.d(tag, "GridView圖像名稱爲:" + girdViewItemName);
- // 把View的色彩濾鏡設置爲綠色。返回true,但返回值將被忽略。
- return (true);
- case DragEvent.ACTION_DRAG_LOCATION:
- // 當拖動陰影還在視圖的邊界框範圍中,視圖的拖動事件監聽器就會在接收到ACTION_DRAG_ENTERED事件
- // 以後接收到這個操做類型的事件。
- // 忽略事件
- return (true);
- case DragEvent.ACTION_DRAG_EXITED:
- /**
- *
- * 當視圖的拖動事件監聽器接收到ACTION_DRAG_ENTERED這個事件,
- * 而且至少接收到一個ACTION_DRAG_LOCATION事件,
- * 那麼在用戶把拖動陰影移除視圖的邊界框範圍以後,該監聽器就會在接收到這個操做類型的事件。
- *
- *
- */
- // 影像離開item視圖
- Log.d(tag, "exited:");
- return (true);
- case DragEvent.ACTION_DROP:
- /**
- *
- * 當用戶在視圖對象上釋放拖動陰影時,該視圖對象的拖動事件監聽器就會接收到這個類型的拖動事件。 這個操做類型只會發送給在迴應
- * ACTION_DRAG_STARTED類型的拖動事件中返回true的那個視圖對象的監聽器
- * 。若是用戶釋放拖動陰影的那個視圖沒有註冊監聽器
- * ,或者用戶在當前佈局以外的任何對象上釋放了拖動陰影,那麼這個操做類型就不會被髮送。
- * 若是釋放動做順利,監聽器應該返回true,不然應該返回false。
- *
- */
- Log.d(tag, "drop:");
- // 顯示一個包含拖動數據的信息
- Toast.makeText(MainActivity.this, "Dragged data is "
- + shadowName, Toast.LENGTH_LONG);
- list.remove(girdViewItemposition);
- list.add(girdViewItemposition, shadowName);
- list.remove(sgadowPosition);
- list.add(sgadowPosition, girdViewItemName);
- adapter.notifyDataSetChanged();
- Log.d("--remove後--", adapter.getList().toString());
- Toast.makeText(MainActivity.this, adapter.getList().toString(),
- Toast.LENGTH_SHORT).show();
- // 返回true。 DragEvent.getResult()也將返回true.
- return (true);
- case DragEvent.ACTION_DRAG_ENDED:
- /**
- * 當系統結束拖動動做時,視圖對象的拖動事件監聽器就會接收到這個類型的拖動事件。
- * 這種操做類型不必定是前面有一個ACTION_DROP事件
- * 。若是系統發送一個ACTION_DROP,並接收到一個ACTION_DRAG_ENDED操做類型
- * ,並不意味着拖動事件的成功。監聽器必須調用getResult()方法來獲取在迴應
- * ACTION_DROP事件中返回的結果。若是ACTION_DROP事件沒有被髮送
- * ,那麼getResult()就返回false。
- */
- // 執行getResult(),顯示操做的結果。
- if (event.getResult()) {
- Toast.makeText(MainActivity.this, "The drop was handled.",
- Toast.LENGTH_LONG);
- } else {
- Toast.makeText(MainActivity.this, "The drop didn't work.",
- Toast.LENGTH_LONG);
- }
- // 返回true; 返回值將被忽略
- return (true);
- // 收到一個未知的action type
- default:
- Log.e("DragDrop Example",
- "Unknown action type received by OnDragListener.");
- break;
- }
- return false;
- }
- }
- }
- grid.setOnItemLongClickListener(new OnItemLongClickListener() {
- @SuppressLint("ParserError")
- @Override
- public boolean onItemLongClick(AdapterView<?> gridView, View view,
- int id, long arg3) {
- shadowName = list.get(id);
- // 爲View設置拖動事件偵聽器
- int count = gridView.getChildCount();
- for (int i = 0; i < count; i++) {
- gridView.getChildAt(i).setOnDragListener(mDragListen);
- }
- // view.setOnDragListener(mDragListen);
- sgadowPosition = id;
- view.setTag(list.get(id));
- Log.d(tag, "長按的圖標名稱是:" + list.get(id));
- ClipData.Item item = new ClipData.Item((CharSequence) view
- .getTag());
- dragData = new ClipData((CharSequence) view.getTag(),
- new String[] { "text/plain" }, item);
- // 實例化drag shadow builder.
- Log.d(tag, "實例化drag shadow builder");
- DragShadowBuilder myShadow = new MyDragShadowBuilder(view);
- // 開始拖動
- Log.d(tag, "開始拖動");
- view.startDrag(dragData, // 要拖動的數據
- myShadow, // drag shadow builder
- null, // 不須要用到本地數據
- 0 // 標誌位(目前未啓用,設爲0)
- );
- return true;
- }
- });