官方介绍:https://developer.android.com/guide/topics/ui/drag-drop.html#AboutDragging
public class MainActivity extends AppCompatActivity {
private ImageView testIv;
private static final String TAG = "imageView";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testIv = (ImageView) findViewById(R.id.test_iv);
testIv.setTag(TAG);
initEvents();
}
private void initEvents() {
testIv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// ClipData.Item对象中包含文字、URI或者Intent数据。一个clip对象中可以包含一个或多个Item对象。
ClipData.Item item = new ClipData.Item(testIv.getTag().toString());
//ClipData代表剪贴板中剪切数据
ClipData dragData = new ClipData(v.getTag().toString(), new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}, item);
//拖放阴影构造者对象,用于构造拖放阴影。
View.DragShadowBuilder myShadow = new MyDragShadowBuilder(testIv);
// 开始拖动
testIv.startDrag(dragData, myShadow, null, 0);
return false;
}
});
testIv.setOnDragListener(new myDragEventListener());
}
//定义了一个myDragShadowBuilder类,它创建一个用于拖拽TextView对象的小的灰色的矩形作为DragShadow
private static class MyDragShadowBuilder extends View.DragShadowBuilder {
private static Drawable shadow;
//构造器接收任意的应用程序的View对象
public MyDragShadowBuilder(View v) {
super(v);
shadow = new ColorDrawable(Color.LTGRAY);
}
/**
* 在你调用startDrag()方法后,系统会立即调用这个方法,给系统发送拖拽影子的尺寸和触点。这个方法有两个参数:
* size:一个Point对象,其中X代表影子的宽度,Y代表影子的高度;
* touch:一个Point对象,这个触点应该是拖拽期间用户手指下方的拖拽影子的位置,X代表x轴的坐标,Y代表y轴的坐标。
*
* @param size
* @param touch
*/
@Override
public void onProvideShadowMetrics(Point size, Point touch) {
int width, height;
width = getView().getWidth() / 2;
height = getView().getHeight() / 2;
shadow.setBounds(0, 0, width, height);
size.set(width, height);
touch.set(width / 2, height / 2);
}
/**
* 调用onProviderShadowMetrics()回调之后,系统会立即调用onDrawShadow()方法来获得拖拽影子。
* 这个方法有一个画布参数(Canvas对象),系统会使用onProvideShadowMetrics()方法中提供的参数来构造这个Canvas对象,
* 并在这个对象中描画拖拽影子。
*
* @param canvas
*/
@Override
public void onDrawShadow(Canvas canvas) {
shadow.draw(canvas);
}
}
//所有的拖拽事件都会被拖拽事件的回调方法或监听器接收。
class myDragEventListener implements View.OnDragListener {
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch (action) {
//只在应用程序调用startDrag()方法,并且获得了拖拽影子后,View对象的拖拽事件监听器才接收这种事件操作。
case DragEvent.ACTION_DRAG_STARTED:
if (event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)) {
testIv.setColorFilter(Color.BLUE);
testIv.invalidate();
return true;
}
return false;
//当拖拽影子刚进入View对象的边框时,View对象的拖拽事件监听器会接收这种事件操作类型。
case DragEvent.ACTION_DRAG_ENTERED:
testIv.setColorFilter(Color.GREEN);
testIv.invalidate();
return true;
//在View对象收到一个ACTION_DRAG_ENTERED事件之后,并且拖拽影子依然还在这个对象的边框之内时,
// 这个View对象的拖拽事件监听器会接收这种事件操作类型
case DragEvent.ACTION_DRAG_LOCATION:
return true;
//View对象收到一个ACTION_DRAG_ENTERED和至少一个ACTION_DRAG_LOCATION事件之后,这个对象的事件监听器会接受这种操作类型。
case DragEvent.ACTION_DRAG_EXITED:
testIv.setColorFilter(Color.BLUE);
testIv.invalidate();
return true;
//当用户在一个View对象之上释放了拖拽影子,这个对象的拖拽事件监听器就会收到这种操作类型。
// 如果这个监听器在响应ACTION_DRAG_STARTED拖拽事件中返回了true,那么这种操作类型只会发送给一个View对象。
// 如果用户在没有被注册监听器的View对象上释放了拖拽影子,或者用户没有在当前布局的任何部分释放操作影子,
// 这个操作类型就不会被发送。如果View对象成功的处理放下事件,监听器要返回true,否则应该返回false。
case DragEvent.ACTION_DROP:
// Gets the item containing the dragged data
ClipData.Item item = event.getClipData().getItemAt(0);
CharSequence dragData = item.getText();
Toast.makeText(MainActivity.this, "Dragged data is " + dragData.toString(), Toast.LENGTH_LONG).show();
testIv.clearColorFilter();
testIv.invalidate();
return true;
//当系统结束拖拽操作时,View对象拖拽监听器会接收这种事件操作类型。
// 这种操作类型之前不一定是ACTION_DROP事件。如果系统发送了一个ACTION_DROP事件,
// 那么接收ACTION_DRAG_ENDED操作类型不意味着放下操作成功了。
// 监听器必须调用getResult()方法来获得响应ACTION_DROP事件中的返回值。
// 如果ACTION_DROP事件没有被发送,那么getResult()会返回false。
case DragEvent.ACTION_DRAG_ENDED:
testIv.clearColorFilter();
testIv.invalidate();
if (event.getResult()) {
Toast.makeText(MainActivity.this, "The drop was handled.", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "The drop didn't work.", Toast.LENGTH_LONG).show();
}
return true;
default:
Log.e("DragDrop Example", "Unknown action type received by OnDragListener.");
break;
}
return false;
}
}
;
}