我们有一个Android应用程序,意味着安装在崎岖地形的车辆的仪表板上,所以一切都非常不稳定。我们发现在这种情况下在屏幕上单击一下是很困难的,因为水龙头通常被解释为小拖拽。
我需要的是触摸事件,在手指出现之前有点摆动被解释为点击,而不是拖动。我一直在阅读“触摸slop”在Android中的工作方式,我可以看到他们已经解释了这一点。我真正需要了解的是如何为Android button
小部件的子类增加'touch slop'。
这只能在几行代码中实现吗?或者我是否需要自己实现onInterceptTouchEvent
和'onTouchEvent`?如果是后者,任何人都可以就这如何运作给我一些指示吗?
答案 0 :(得分:1)
这是我做的,希望能帮到你们。
private Rect mBtnRect;
yourView.setOnTouchListener(new OnTouchListener() {
private boolean isCancelled = false;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isCancelled = false;
parent.requestDisallowInterceptTouchEvent(true); // prevent parent and its ancestors to intercept touch events
createClickArea(v);
// your logic touch down
return true;
case MotionEvent.ACTION_UP:
if(!isCancelled) {
// Click logic
}
// release mBtnRect when cancel or up event
mBtnRect = null;
return true;
case MotionEvent.ACTION_CANCEL:
isCancelled = true;
releaseTouch(parent, v);
return true;
case MotionEvent.ACTION_MOVE:
if(!isBelongTouchArea(event.getRawX(), event.getRawY())) {
isCancelled = true;
releaseTouch(parent, v);
}
return true;
default:
break;
}
}
// Create the area from the view that user is touching
private final void createClickArea(View v) {
// for increase rect area of button, pixel in used.
final int delta = (int) mContext.getResources().getDimension(R.dimen.extension_area);
final int[] location = new int[2];
// Get the location of button call on screen
v.getLocationOnScreen(location);
// Create the rect area with an extension defined distance.
mBtnRect = new Rect(v.getLeft() - delta, location[1] + v.getTop() - delta, v.getRight(), location[1] + v.getBottom() + delta);
}
//Check the area that contains the moved position or not.
private final boolean isBelongTouchArea(float rawX, float rawY) {
if(mBtnRect != null && mBtnRect.contains((int)rawX, (int)rawY)) {
return true;
}
return false;
}
private void releaseTouch(final ListView parent, View v) {
parent.requestDisallowInterceptTouchEvent(false);
mBtnRect = null;
// your logic
}
答案 1 :(得分:1)
对于我们使用android.opengl.GLSurfaceView
的简单用例,我们解决了您遇到的同样问题,"如果在手势中移动的距离小于 some_threshold ,将其解释为点击"。我们使用两个2D点之间的标准欧几里德距离= sqrt((deltaX)^2 + (deltaY)^2))
,其中deltaX
和deltaY
是 X 和 Y 组件在用户的动作手势中移动的距离。
更准确地说,让(x1,y1)
成为用户手指手势' 的坐标,让(x2,y2)
成为手势的坐标< EM>&#39;截止&#39;
然后,deltaX = x2 - x1
(或者它也可以是x1 - x2
但是符号对于距离并不重要&c; cz我们对值进行平方)并且类似于deltaY
从这些增量中,我们计算欧几里德距离,如果它小于阈值,用户可能打算将其作为点击,但由于设备的触摸slop,它被归类为 move 手势而不是点击。
实施方面,是的,我们覆盖了android.view.View#onTouchEvent(MotionEvent)
和
(x1,y1)
或android.view.MotionEvent#ACTION_POINTER_DOWN
android.view.MotionEvent#ACTION_DOWN
android.view.MotionEvent#ACTION_MOVE
时,(x2,y2)
和getX
方法可以随时提供getY
(请参阅corresponding documentation)< / LI>