首先由文档中介绍所说,drag and drop手势是用于将一个View中的数据放到另一个View中,同时还可以用于UI相关的动作
其次其应用的步骤为:首先新建一个类实现View.OnDragListener,该类用于drag and drop事件发生时的回调,然后再新建一个类继承自View.DragShadowBuilder用于设置动作发生时随拖动而移动的阴影图像,最后设置监听,然后在当你认为该动作是为了触发drag and drop时调用View的startDrag方法即可。
值得注意的就是当用户手指在当前的布局上拖拽阴影时,系统会向当前的注册了dragListener的View发送drag event,这里的View是当前布局上所有的View,假设你有6个View都注册了dragListener,那么当其中一个View调用startDrag方法时,其他的View的drag_start事件同样发生。
下面是一个小例子,在5个ImageView均可拖动,当拖动一个到另一个ImageView上drop时,则交换二个ImageView的src图片
public class MainActivity extends Activity {
private ImageView imageView[];
private TextView textView;
private int []imageId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.text);
textView.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
return true;
}
});
imageView = new ImageView[5];
imageId=new int[5];
myDragEventListener dragEventListener = new myDragEventListener();
for (int i = 0; i < 5; i++) {
int id = getResources().getIdentifier("image_view0" + (i + 1), "id", getPackageName());
imageView[i] = (ImageView) findViewById(id);
imageView[i].setOnDragListener(dragEventListener);
imageView[i].setTag(i);
final int finalI = i;
final int bid = getResources().getIdentifier("a" + (i + 1), "drawable", getPackageName());
imageId[i]=bid;
imageView[i].setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
View.DragShadowBuilder myShadow = new MyDragShadowBuilder(imageView[finalI], getResources(), imageId[finalI]);
v.startDrag(null, myShadow, null, 0);
return true;
}
});
}
}
/**
* 该类用于构造显示拖拽的阴影
*/
private static class MyDragShadowBuilder extends View.DragShadowBuilder {
private static Drawable shadow;
/**
* 构造阴影
* @param v
* @param res
* @param id
*/
public MyDragShadowBuilder(View v, Resources res, int id) {
super(v);
shadow = new BitmapDrawable(BitmapFactory.decodeResource(res,id));
shadow.setAlpha(126);
}
/**
* 设定阴影的大小、手指位于阴影的位置
* @param size
* @param touch
*/
@Override
public void onProvideShadowMetrics(Point size, Point touch) {
int width, height;
width = getView().getWidth();
height = getView().getHeight();
shadow.setBounds(0, 0, width, height);
size.set(width, height);
touch.set(width / 2, height / 2);
}
/**
* 将阴影绘制到canvas上以以供显示
* @param canvas
*/
@Override
public void onDrawShadow(Canvas canvas) {
shadow.draw(canvas);
}
}
/**
* 拖拽事件的回调
*/
protected class myDragEventListener implements View.OnDragListener {
private ImageView image;
private boolean flag;
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch (action) {
//当拖拽手势开始时调用,当前布局上所有注册了dragListener的View的相应事件都发生回调
case DragEvent.ACTION_DRAG_STARTED:
flag=true;
return true;
//当拖拽的阴影进入View时回调
case DragEvent.ACTION_DRAG_ENTERED:
if(flag){//第一个为要拖拽的View,将至隐藏
flag=false;
image= (ImageView) v;
image.setVisibility(View.INVISIBLE);
}
else {
((ImageView) v).setColorFilter(Color.parseColor("#cccccccc"), PorterDuff.Mode.LIGHTEN);
}
v.invalidate();
return true;
//拖拽的阴影位于当前View时回调
case DragEvent.ACTION_DRAG_LOCATION:
return true;
//拖拽的阴影离开View时回调
case DragEvent.ACTION_DRAG_EXITED:
((ImageView) v).clearColorFilter();
v.invalidate();
return true;
//拖拽的阴影放入数据到View时回调
case DragEvent.ACTION_DROP:
((ImageView)v).clearColorFilter();
Drawable d=((ImageView)v).getDrawable();
((ImageView)v).setImageDrawable(image.getDrawable());
image.setImageDrawable(d);
image.setVisibility(View.VISIBLE);
int index1= (int) v.getTag();
int index2= (int) image.getTag();
int tmp=imageId[index2];
imageId[index2]=imageId[index1];
imageId[index1]=tmp;
v.invalidate();
return true;
//托拽事件结束时所有View的事件回调
case DragEvent.ACTION_DRAG_ENDED:
((ImageView) v).clearColorFilter();
if (event.getResult()) {//如果该拖拽存在数据且DROP事件被处理了,则返回值为真
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();
}
v.invalidate();
return true;
}
return false;
}
}
}
布局文件很简单,就是一个LinearLayout中垂直放置了5个ImageView和一个TextView