项目有个需求,要做类似android桌面的删除功能,为此研究了一天,做了个demo出来
XML代码如下
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageButton
android:id="@+id/imageButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:contentDescription="@string/app_name"
android:background="@drawable/trashcan" />
<ImageView
android:id="@+id/select"
android:layout_width="100dp"
android:layout_height="200dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
以上XML很简单,定义了两个view,一个是拖动的view,一个是接收的view
ontouch代码如下
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int ea = event.getAction();
System.out.println("event.getAction() " + ea);
switch (ea) {
case MotionEvent.ACTION_DOWN:
lastX = (int) event.getRawX();// 获取触摸事件触摸位置的原始X坐标
lastY = (int) event.getRawY();
int[] location = new int[2];
iv.getLocationInWindow(location);
xx = location[0];
yy = location[1];
yy1 = iv.getHeight();
Log.e("demo", "Window--->" + xx + " " + "Window--->" + yy
+ "Window--->" + (yy1 + yy));
l1 = v.getLeft();
t1 = v.getTop();
r1 = v.getRight();
b1 = v.getBottom();
break;
case MotionEvent.ACTION_MOVE:
if ((int) event.getRawX() > xx
&& ((int) event.getRawY() > yy && (int) event
.getRawY() < (yy1 + yy))) {
iv.setBackgroundResource(R.color.color1);
selected = true;
} else {
iv.setBackgroundResource(R.color.color2);
selected = false;
}
// Log.e("~~~~",
// (int) event.getRawX() + "!!!!"
// + (int) event.getRawY());
int dx = (int) event.getRawX() - lastX;
int dy = (int) event.getRawY() - lastY;
int l = v.getLeft() + dx;
int t = v.getTop() + dy;
int r = v.getRight() + dx;
int b = v.getBottom() + dy;
Log.e("!!", "当前位置:" + v.getLeft() + "," + v.getTop() + "," + v.getRight() + "," + v.getBottom());
// 下面判断移动是否超出屏幕
if (l < 0) {
l = 0;
r = l + v.getWidth();
}
if (t < 0) {
t = 0;
b = t + v.getHeight();
}
if (r > screenWidth) {
r = screenWidth;
l = r - v.getWidth();
}
if (b > screenHeight) {
b = screenHeight;
t = b - v.getHeight();
}
v.layout(l, t, r, b);
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
// Log.e("!!", "当前位置:" + l + "," + t + "," + r + "," + b);
v.postInvalidate();
break;
case MotionEvent.ACTION_UP:
if (selected) {
iv.setBackgroundResource(R.color.color3);
}
v.layout(l1, t1, r1, b1);
break;
以上代码定义了拖动view时的ontouch时间,当ACTION_DOWN时记录该view的初始位置,ACTION_MOVE时计算出每一次MOVE的偏移量dx,dy,再计算出该view应该出现位置的上下左右坐标,然后将该view更新于此,ACTION_UP判断当前位置是否在接收view之上,然后将view还原到初始位置
在实际应用时,并没有使用该方法
我的项目需求准确的说是在SurfaceView上层的一个popupwindow上的view拖动删除,首先一点,popupwindow上的view通过该方法不能拖动出它的父窗口,所以该方法不适用
其次,因为之前还有一个想法是长按该删除view时将其隐藏,然后在SurfaceView上new一个新的view并通过touch的坐标移动该view,但是SurfaceView会覆盖掉所有在其上层的view,所以这个也行不通。
最后的解决办法就是长按后将该view隐藏,新建一个popupwindow,showAtLocation到隐藏的位置,因为新建的popupwindow会置于所有popupwindow之上,通过popupwindow的update的方法根据touch坐标改变其位置实现拖动效果。