位置:首頁 > 手機開發 > Android開發教學 > Android拖放

Android拖放

Android 拖/放框架允許用戶將數據從一個View到另一個視圖在當前布局中使用圖形化的拖放動作。該框架包括以下三個重要組成部分,支持拖放功能:

  • 拖動事件類

  • 拖動監聽器

  • 輔助方法和類

拖放過程

基本上有四個步驟,在拖放過程或狀態:

  • 開始:此事件發生時開始拖動布局中的一個項目,應用類的tartDrag()方法來告訴係統啟動拖動。startDrag()方法的參數提供被拖動的數據,這些是數據的元數據和一個回調用於繪製的拖動陰影。

    該係統首先通過回調應用程序,以獲得一個拖陰影的響應。然後顯示在設備上的拖影。

    接下來,係統會發送拖曳事件動作類型ACTION_DRAG_STARTED在當前布局中的所有視圖對象拖動事件監聽器注冊。

    若要繼續接收拖動事件,其中包括一個可能的放事件,一個拖事件偵聽器必須返回true,如果拖動事件偵聽器返回false,那麼它不會收到拖動事件當前的操作,直到係統發送一個動作類型的拖曳事件ACTION_DRAG_ENDED。

  • 繼續:用戶可以繼續拖動。係統發送ACTION_DRAG_ENTERED動作,其次注冊拖動事件偵聽器的視圖中拖動點進入ACTION_DRAG_LOCATION動作。響應該事件監聽器可以選擇改變其對象的外觀或可以凸顯其觀點反應。用戶移動拖動視圖的邊框陰影外拖曳事件偵聽器接收ACTION_DRAG_EXITED動作。

  • 拖動:用戶釋放拖動的項目視圖的邊框內。該係統發送對象的偵聽器拖動事件使用動作類型ACTION_DROP。

  • 結果:操作類型ACTION_DROP之後,係統發出一個操作類型ACTION_DRAG_ENDED表示拖動操作結束的拖動事件。

DragEvent 類

dragEvent代表一個事件,就會由係統送出拖放操作過程中在不同的時間。這個類提供了一些常量和重要的方法在使用拖/放過程。

常量

以下是所有常量作為部分 dragEvent 類整數。

S.N. 常量說明
1 ACTION_DRAG_STARTED 
拖放操作的開始的信號
2 ACTION_DRAG_ENTERED 
一種視圖拖動點已進入視圖的邊框的信號
3 ACTION_DRAG_LOCATION 
發送到ACTION_DRAG_ENTERED後的視圖,如果拖影依然是查看對象的邊框內
4 ACTION_DRAG_EXITED 
信號的用戶移動拖動陰影視圖的邊框之外
5 ACTION_DROP 
信號到View用戶發布了拖影,而阻力點就是視圖的邊框內
6 ACTION_DRAG_ENDED 
視圖拖放操作已經結束信號

方法

以下是作為部分的 dragEvent 類提供一些重要的和最常用的方法。

S.N. 常量說明
1 int getAction() 
檢查此事件的動作值
2 ClipData getClipData() 
返回對象到係統調用ClipData()發送作為到startDrag一部分部分
3 ClipDescription getClipDescription() 
返回包含在ClipData的ClipDescription對象
4 boolean getResult() 
返回拖放操作的結果的指示
5 float getX() 
獲取阻力的X坐標點
6 float getY() 
獲取阻力的Y坐標點
7 String toString() 
返回DragEvent對象的字符串表示

監聽拖放事件

如果想要的任何布局內視圖響應拖動事件,那麼視圖要麼實現 View.OnDragListener 或者設置 onDragEvent(DragEvent) 回調方法。當係統調用的方法或監聽器,它傳遞給上述 dragEvent 對象。可以查看對象的監聽器和一個回調方法。如果發生這種情況,係統首先調用監聽器,然後定義回調監聽器返回true。

組合 onDragEvent(DragEvent)方法 和 View.OnDragListener,類似於 onTouchEvent() 和 View.OnTouchListener 使用在舊版本 Android 觸摸事件的組合。 

開始拖動事件

開始創建ClipData和移動數據ClipData.Item。作為ClipDataobject 的一部分提供的元數據被存儲在ClipDescription內ClipData對象。對於拖放操作,並不代表數據移動,可能想使用空(null)而不是實際的對象。

下一步,可以擴展 View.DragShadowBuilder 創建一個拖動視圖,或者使用 View.DragShadowBuilder(View) 創建一個默認的大小相同的View參數傳遞給它的拖影,觸摸拖動陰影點集中在拖影。

示例

下麵的例子顯示了一個簡單的拖放示例中使用View.setOnLongClickListener() 事件偵聽器和 View.OnDragEventListener().函數。 

步驟 描述
1 使用Android Studio創建Android應用程序,並將它命名為:DragNDropDemo。在創建這個項目,確保目標SDK和編譯在Android SDK的最新版本或使用更高級彆的API。
2 修改 src/MainActivity.java 文件,並添加定義事件偵聽器的代碼,以及一個回調方法,在這個例子中使用Logo圖像
3 複製圖片logo.png到res/drawable-* 文件夾。可以使用的情況下,要為他們提供了不同的設備有不同的分辨率的圖像
4 修改布局文件 res/layout/activity_main.xml l定義logo圖片的默認視圖
5 運行該應用程序啟動 Android模擬器並驗證應用程序所做的修改結果。

以下是修改主活動文件 src/com.yiibai.dragndropdemo/MainActivity.java 。這個文件可以包括每個生命周期基本方法。

package com.yiibai.dragndropdemo;

import android.os.Bundle;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.util.Log;
import android.view.DragEvent;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.widget.*;

public class MainActivity extends Activity{
   ImageView ima;
   private static final String IMAGEVIEW_TAG = "Android Logo";
   String msg;

   private android.widget.RelativeLayout.LayoutParams layoutParams;

   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      ima = (ImageView)findViewById(R.id.iv_logo);
      // Sets the tag
      ima.setTag(IMAGEVIEW_TAG);

      ima.setOnLongClickListener(new View.OnLongClickListener() {
         @Override
         public boolean onLongClick(View v) {
            ClipData.Item item = new ClipData.Item((CharSequence)v.getTag());

            String[] mimeTypes = {ClipDescription.MIMETYPE_TEXT_PLAIN};
            ClipData dragData = new ClipData(v.getTag().toString(), 
            mimeTypes, item);

            // Instantiates the drag shadow builder.
            View.DragShadowBuilder myShadow = new DragShadowBuilder(ima);

            // Starts the drag
            v.startDrag(dragData,  // the data to be dragged
            myShadow,  // the drag shadow builder
            null,      // no need to use local data
            0          // flags (not currently used, set to 0)
            );
            return true;
         }
      });

      // Create and set the drag event listener for the View
      ima.setOnDragListener( new OnDragListener(){
         @Override
         public boolean onDrag(View v,  DragEvent event){
         RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) v.getLayoutParams();
         switch(event.getAction())                   
         {
            case DragEvent.ACTION_DRAG_STARTED:
               layoutParams = (RelativeLayout.LayoutParams) 
               v.getLayoutParams();
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_STARTED");
               // Do nothing
               break;
            case DragEvent.ACTION_DRAG_ENTERED:
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_ENTERED");
               int x_cord = (int) event.getX();
               int y_cord = (int) event.getY();  
               break;
            case DragEvent.ACTION_DRAG_EXITED :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_EXITED");
               x_cord = (int) event.getX();
               y_cord = (int) event.getY();
               layoutParams.leftMargin = x_cord;
               layoutParams.topMargin = y_cord;
               v.setLayoutParams(layoutParams);
               break;
            case DragEvent.ACTION_DRAG_LOCATION  :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_LOCATION");
               x_cord = (int) event.getX();
               y_cord = (int) event.getY();
               break;
            case DragEvent.ACTION_DRAG_ENDED   :
               Log.d(msg, "Action is DragEvent.ACTION_DRAG_ENDED");
               // Do nothing
               break;
            case DragEvent.ACTION_DROP:
               Log.d(msg, "ACTION_DROP event");
               // Do nothing
               break;
            default: break;
            }
            return true;
         }
      });
   }
}

下麵是 res/layout/activity_main.xml 文件的內容:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
	
    <ImageView
		android:id="@+id/iv_logo" 
    	android:layout_width="wrap_content" 
    	android:layout_height="wrap_content"
    	android:src="@drawable/logo"
    	android:contentDescription="@string/drag_drop"  />
	   
</RelativeLayout>

下麵文件 res/values/strings.xml 的內容中定義兩個新的常量:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">DragNDropDemo</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="drag_drop">Click on the image to drag and drop</string>
   
</resources>

以下是 AndroidManifest.xml 文件的默認內容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yiibai.guidemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.yiibai.guidemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我們嘗試運行 DragNDropDemo 應用程序。AVD安裝的應用程序,並啟動它,如果一切設置和應用都冇有問題,它會顯示以下模擬器窗口: 

Android拖放

現在長時間點擊顯示Android的標誌,會看到標誌圖像經過1秒長的點擊它,開始拖動圖像的時候移動了一點。可以拖動它在屏幕上,並把它放在一個新的位置。

Android拖放

以下代碼下載:http://pan.baidu.com/s/1eQIQIjw