OnTouch MotionEvent 动作移动未触发
OnTouch MotionEvent Action Move not triggering
我试图在拖动按钮时获取 X、Y 坐标,但由于某种原因,触摸侦听器上附加的代码波纹管仅触发两次,而不是在拖动时不断更新,即使有 trothing 我也会为了提高性能而感到满意,但正如我所说,onTouch
方法仅在动作停止时触发,然后再触发一次。
这是我的代码:
final Button dragBtn = (Button) findViewById(R.id.MyTestButton);
dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadow = new View.DragShadowBuilder(dragBtn);
v.startDrag(data, shadow, null, 0);
int action = me.getAction();
if (action==MotionEvent.ACTION_DOWN) {
Log.i("TEST", "ACTION_DOWN");
return true;
}
if (action==MotionEvent.ACTION_MOVE){
Log.i("TEST", "ACTION_MOVE");
float x = me.getX();
float y = me.getY();
//TODO: Rest of my code here.
return true;
}
if (action==MotionEvent.ACTION_UP){
Log.i("TEST", "ACTION_UP");
return true;
}
Log.i("TEST", "UKNOWN ACTION");
return true;
}
});
在日志中我刚刚:
ACTION_DOWN
WindowManager﹕ Drag already in progress
UKNOWN ACTION
MotionEvent.getAction 编码动作类型以及额外的指针信息(用于多点触摸处理)。您希望 MotionEvent.getActionMasked 只获得动作部分。
编辑:另外,根据下面的讨论,startDragging 存在一些问题。
最后你的代码应该是这样的。
int basex;
int basey;
RelativeLayout.LayoutParams layoutParams;
RelativeLayout layBg;
....................
dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
layoutParams = (RelativeLayout.LayoutParams) dragBtn.getLayoutParams();
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN:
basex = ((int) (me.getRawX() - layoutParams.leftMargin));
basey = ((int) (me.getRawY() - layoutParams.topMargin));
break;
case MotionEvent.ACTION_MOVE:
int i = (int) event.getRawX();
int j = (int) event.getRawY();
layBg = ((RelativeLayout) dragBtn.getParent());
if ((i - basex > -(dragBtn.getWidth() * 2 / 3))
&& (i - basex < layBg.getWidth() - dragBtn.getWidth() / 3)) {
layoutParams.leftMargin = (i - basex);
}
if ((j - basey > -(dragBtn.getHeight() * 2 / 3))
&& (j - basey < layBg.getHeight() - dragBtn.getHeight() / 3)) {
layoutParams.topMargin = (j - basey);
}
layoutParams.rightMargin = -1000;
layoutParams.bottomMargin = -1000;
dragBtn.setLayoutParams(layoutParams);
break;
}
return true;
}
});
一旦系统有了拖动阴影,它就会通过向应用程序中当前可见的所有 View 对象发送拖动事件来开始拖放操作。它通过调用 View 对象的拖动侦听器(onDrag() 的实现)或通过调用 View 对象的 onDragEvent() 方法来实现。两者都传递了一个 DragEvent 对象,该对象的 getAction() 值为 ACTION_DRAG_STARTED
您想在 OnDragListener
而不是 OnTouchListener
中捕获 X 和 Y 坐标数据。在您围绕屏幕拖动对象的整个过程中,Android 将其解释为单个 ACTION_MOVE 事件,因此您只能从中获取一次数据。将以下代码放入您的自定义 OnDragListener
class:
@Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
float xCoord;
float yCoord;
if(action == DragEvent.ACTION_DRAG_LOCATION) {
xCoord = event.getX();
yCoord = event.getY();
}
return event.getResult(); //returns true for valid drop or false for invalid drop
}
在您的自定义 OnDragListener
class 中的其他地方,您必须对 xCoord 和 yCoord 数据进行一些处理。例如,在我的应用程序中,我在 "debug" 版本的应用程序中有一个 TextView
显示 xCoord 和 yCoord 数据。在 if(action == DragEvent.ACTION_DRAG_LOCATION){...
部分获得这两个值后,我立即执行 TextView.setText()
方法。
希望对您有所帮助。
我试图在拖动按钮时获取 X、Y 坐标,但由于某种原因,触摸侦听器上附加的代码波纹管仅触发两次,而不是在拖动时不断更新,即使有 trothing 我也会为了提高性能而感到满意,但正如我所说,onTouch
方法仅在动作停止时触发,然后再触发一次。
这是我的代码:
final Button dragBtn = (Button) findViewById(R.id.MyTestButton);
dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadow = new View.DragShadowBuilder(dragBtn);
v.startDrag(data, shadow, null, 0);
int action = me.getAction();
if (action==MotionEvent.ACTION_DOWN) {
Log.i("TEST", "ACTION_DOWN");
return true;
}
if (action==MotionEvent.ACTION_MOVE){
Log.i("TEST", "ACTION_MOVE");
float x = me.getX();
float y = me.getY();
//TODO: Rest of my code here.
return true;
}
if (action==MotionEvent.ACTION_UP){
Log.i("TEST", "ACTION_UP");
return true;
}
Log.i("TEST", "UKNOWN ACTION");
return true;
}
});
在日志中我刚刚:
ACTION_DOWN
WindowManager﹕ Drag already in progress
UKNOWN ACTION
MotionEvent.getAction 编码动作类型以及额外的指针信息(用于多点触摸处理)。您希望 MotionEvent.getActionMasked 只获得动作部分。
编辑:另外,根据下面的讨论,startDragging 存在一些问题。
最后你的代码应该是这样的。
int basex;
int basey;
RelativeLayout.LayoutParams layoutParams;
RelativeLayout layBg;
....................
dragBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent me) {
// TODO Auto-generated method stub
layoutParams = (RelativeLayout.LayoutParams) dragBtn.getLayoutParams();
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN:
basex = ((int) (me.getRawX() - layoutParams.leftMargin));
basey = ((int) (me.getRawY() - layoutParams.topMargin));
break;
case MotionEvent.ACTION_MOVE:
int i = (int) event.getRawX();
int j = (int) event.getRawY();
layBg = ((RelativeLayout) dragBtn.getParent());
if ((i - basex > -(dragBtn.getWidth() * 2 / 3))
&& (i - basex < layBg.getWidth() - dragBtn.getWidth() / 3)) {
layoutParams.leftMargin = (i - basex);
}
if ((j - basey > -(dragBtn.getHeight() * 2 / 3))
&& (j - basey < layBg.getHeight() - dragBtn.getHeight() / 3)) {
layoutParams.topMargin = (j - basey);
}
layoutParams.rightMargin = -1000;
layoutParams.bottomMargin = -1000;
dragBtn.setLayoutParams(layoutParams);
break;
}
return true;
}
});
一旦系统有了拖动阴影,它就会通过向应用程序中当前可见的所有 View 对象发送拖动事件来开始拖放操作。它通过调用 View 对象的拖动侦听器(onDrag() 的实现)或通过调用 View 对象的 onDragEvent() 方法来实现。两者都传递了一个 DragEvent 对象,该对象的 getAction() 值为 ACTION_DRAG_STARTED
您想在 OnDragListener
而不是 OnTouchListener
中捕获 X 和 Y 坐标数据。在您围绕屏幕拖动对象的整个过程中,Android 将其解释为单个 ACTION_MOVE 事件,因此您只能从中获取一次数据。将以下代码放入您的自定义 OnDragListener
class:
@Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
float xCoord;
float yCoord;
if(action == DragEvent.ACTION_DRAG_LOCATION) {
xCoord = event.getX();
yCoord = event.getY();
}
return event.getResult(); //returns true for valid drop or false for invalid drop
}
在您的自定义 OnDragListener
class 中的其他地方,您必须对 xCoord 和 yCoord 数据进行一些处理。例如,在我的应用程序中,我在 "debug" 版本的应用程序中有一个 TextView
显示 xCoord 和 yCoord 数据。在 if(action == DragEvent.ACTION_DRAG_LOCATION){...
部分获得这两个值后,我立即执行 TextView.setText()
方法。
希望对您有所帮助。