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_ENTERED、ACTION_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:用于拖放的移動資料。
code
<?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>
為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;
}
});
imageView的位置
topContainer.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch (action) {
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DRAG_ENTERED:
return true;
case DragEvent.ACTION_DRAG_LOCATION:
return true;
case DragEvent.ACTION_DRAG_EXITED:
return true;
case DragEvent.ACTION_DROP:
imageView.setX(event.getX()-imageView.getWidth()/2);
imageView.setY(event.getY()-imageView.getHeight()/2);
return true;
case DragEvent.ACTION_DRAG_ENDED:
return true;
default:
break;
}
return false;
}
});
效果

我是天王蓋地虎的分割線
轉載:http://www.cnblogs.com/jerehedu/p/4427588.html
作者:我愛物聯網
出處:http://yydcdut.cnblogs.com/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。