Android開發之Drag&Drop框架實現拖放手勢


  Android3.0提供了drag/drop框架,利用此框架可以實現使用拖放手勢將一個view拖放到當前布局中的另外一個view中。本文將介紹如何使用拖放框架。

一、實現拖放的步驟

   首先,我們先了解一下拖放過程,從官方文檔可以知道,整個拖放過程共分為4個步驟,具體如下:

  1、  Started:啟動拖放,主要是調用被拖放View的startDrag方法。此方法原型為:

public final boolean startDrag(ClipData data,

                View.DragShadowBuilder shadowBuilder,

                Object myLocalState,

                int flags)

  啟動后,系統生成拖放陰影並發送action為ACTION_DRAG_STARTED的拖放事件到當前布局中已經設置了拖放監聽的View。

  2、  Continuing:保持拖動狀態。在此過程中系統可能會發送一個或多個拖動事件給設置了拖放監聽器的View,比如ACTION_DRAG_ENTEREDACTION_DRAG_LOCATION等。

  3、  Dropped:用戶在目標區域內釋放拖動陰影,系統會向設置了拖放監聽器的View發送action為ACTION_DROP的事件。

  4、  Ended:用戶釋放了拖動陰影,系統會向設置了拖放監聽器的View發送action為ACTION_DRAG_ENDED事件,完成拖放。

二、拖放過程中關鍵的接口和類

   其次,我們要了解清楚拖放過程中的幾個關鍵的接口和類,主要有OnDragListener、DragEvent、DragShadowBuilder、ClipData、ClipDescription等。

  1、OnDragListener:接口,拖放事件監聽器。當發生Drag時,回調此接口中的方法。接口中只含有一個方法onDrag,方法原型為:

   boolean onDrag(View v, DragEvent event)

   參數v:設置了監聽器的View

   參數event:拖放事件的參數,封裝了拖放相關的數據

   返回值:true-事件已處理;false事件未處理。

  2、DragEvent:拖放事件對象,根據action的不同,包含不同的事件數據。

  3、DragShadowBuilder:拖放陰影構造者對象,用於構造拖放陰影。

  4、ClipData、ClipDescription:用於拖放的移動數據。

三、案例展示

   對以上內容有了基本了解后,我們來進行如下案例,首先看效果圖

  如圖界面內共有兩個區域,灰色區域和黃色區域,圖標可在灰色區域內自由拖動,並可改變自己的位置,如下圖

 

  當圖標進入或離開黃色區域時,將改變顏色,效果圖如下

四、案例實現

   下面我們看看具體如何實現:

  布局文件,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/topContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@null"
        android:src="@drawable/ic_launcher" />

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"
        android:background="#cccccc" >
        <TextView
            android:id="@+id/title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:textColor="#ff0000"
            android:textSize="18sp" />
    </LinearLayout>

</RelativeLayout>

  Java文件:

  為ImageView綁定長點擊事件

imageView.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                //創建移動數據
                ClipData.Item item = new ClipData.Item((String) v.getTag());
                ClipData data = new ClipData(IMAGEVIEW_TAG,
                        new String[] { ClipDescription.MIMETYPE_TEXT_PLAIN },
                        item);
                //調用startDrag方法,第二個參數為創建拖放陰影
                v.startDrag(data, new View.DragShadowBuilder(v), null, 0);
                return true;
            }
        });

  為目標View綁定拖拽監聽:

container.setOnDragListener(new OnDragListener() {
            @Override
            public boolean onDrag(View v, DragEvent event) {
                final int action = event.getAction();
                switch (action) {
                case DragEvent.ACTION_DRAG_STARTED:
                    //拖拽開始事件
                    if (event.getClipDescription().hasMimeType(
                            ClipDescription.MIMETYPE_TEXT_PLAIN)) {
                        return true;
                    }
                    return false;
                case DragEvent.ACTION_DRAG_ENTERED:
                    //被拖放View進入目標View
                    container.setBackgroundColor(Color.YELLOW);
                    return true;
                case DragEvent.ACTION_DRAG_LOCATION:
                    return true;
                case DragEvent.ACTION_DRAG_EXITED:
                    //被拖放View離開目標View
                    container.setBackgroundColor(Color.BLUE);
                    title.setText("");
                    return true;
                case DragEvent.ACTION_DROP:
                    //釋放拖放陰影,並獲取移動數據
                    ClipData.Item item = event.getClipData().getItemAt(0);
                    String dragData = item.getText().toString();
                    title.setText(dragData+event.getY()+":"+event.getX());
                    return true;
                case DragEvent.ACTION_DRAG_ENDED:
                    //拖放事件完成
                    return true;
                default:
                    break;
                }
                return false;
            }
        });
五、源碼下載

  想要動手實踐的小伙伴,可以點擊“源碼下載”下載完整工程測試。

 

作者: 傑瑞教育
出處: http://www.cnblogs.com/jerehedu/ 
本文版權歸煙台傑瑞教育科技有限公司和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM