【问题标题】:Android MotionEvent: find out if motion happened outside the viewAndroid MotionEvent:找出运动是否发生在视图之外
【发布时间】:2012-06-25 16:43:02
【问题描述】:
我有一个按钮和 OnTouchListener 附加到它。我怎样才能找到运动(当用户按下按钮时)发生在它内部还是外部? event.getAction() 和 event.getActionMasked() 都只返回 0、1 或 2,分别是 ActionDown、ActionUp、ActionMove。有一个常量 MotionEvent.ACTION_OUTSIDE,即 4,但不知何故,即使我将触摸拖到按钮外,我也没有收到它 - 我仍然从两种方法中收到 2。有什么问题?
UPD:我找到了很好的解决方案 - 只需在 ACTION_UP 之后检查视图中的焦点状态。如果它没有聚焦,则意味着运动发生在视图之外。
【问题讨论】:
标签:
android
motion-detection
【解决方案1】:
该标志仅适用于 Windows,不适用于视图。当您将手指从视图上移开时,您将获得ACTION_MOVE,事件将保留在它起源的视图中。如果您需要澄清,请查看SeekBar 的源代码:即使您将手指从栏上移开,拇指仍然会拖动!
要在窗口级别执行此操作,请使用FLAG_WATCH_OUTSIDE_TOUCH,它工作得很好。
【解决方案2】:
如果OnTouchListener 在Button 上,您将只能从Button 中接收运动事件。 MotionEvent.ACTION_OUTSIDE 只会在运动事件第一次超出 View 的范围时被调用,您应该像对待 ACTION_UP 一样对待它。
【解决方案3】:
case MotionEvent.ACTION_CANCEL 为我工作。
【解决方案4】:
MotionEvent.ACTION_OUTSIDE 不适用于 View。
一种解决方案是获取 X 和 Y 触摸位置并验证它是否在视图的边界内。可以这样做:
@Override
public boolean onTouchEvent(MotionEvent e) {
if (isInside())
Log.i(TAG, "TOUCH INSIDE");
else
Log.i(TAG, "TOUCH OUTSIDE");
return true;
}
private boolean isInside(View v, MotionEvent e) {
return !(e.getX() < 0 || e.getY() < 0
|| e.getX() > v.getMeasuredWidth()
|| e.getY() > v.getMeasuredHeight());
}
【解决方案5】:
public static boolean touchWithinBounds(MotionEvent event, View view) {
if (event == null || view == null || view.getWidth() == 0 || view.getHeight() == 0)
return false;
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
int viewMaxX = viewLocation[0] + view.getWidth() - 1;
int viewMaxY = viewLocation[1] + view.getHeight() - 1;
return (event.getRawX() <= viewMaxX && event.getRawX() >= viewLocation[0]
&& event.getRawY() <= viewMaxY && event.getRawY() >= viewLocation[1]);
}
从不同视图转发触摸事件时的解决方案