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