增加Android按钮中的触摸斜率

增加Android按钮中的触摸斜率,android,button,touch-event,Android,Button,Touch Event,我们有一个安卓应用程序,安装在崎岖地形下行驶的车辆仪表板上,所以一切都很不稳定。我们发现,在这种情况下,在屏幕上进行一次点击是困难的,因为点击通常被解释为小阻力 我需要的是在手指出现之前有一点晃动的触摸事件被解释为点击,而不是拖动。我一直在阅读安卓系统中触摸屏的工作方式,我可以看到他们已经解释了这一点。我真正需要了解的是,如何为Android按钮小部件的子类增加“touch slop” 仅仅几行代码就可以做到这一点吗?或者我需要自己实现onInterceptTouchEvent和“onTouch

我们有一个安卓应用程序,安装在崎岖地形下行驶的车辆仪表板上,所以一切都很不稳定。我们发现,在这种情况下,在屏幕上进行一次点击是困难的,因为点击通常被解释为小阻力

我需要的是在手指出现之前有一点晃动的触摸事件被解释为点击,而不是拖动。我一直在阅读安卓系统中触摸屏的工作方式,我可以看到他们已经解释了这一点。我真正需要了解的是,如何为Android
按钮
小部件的子类增加“touch slop”


仅仅几行代码就可以做到这一点吗?或者我需要自己实现
onInterceptTouchEvent
和“onTouchEvent”吗?如果是后者,谁能给我一些关于如何工作的指导吗?

以下是我所做的,希望能对你们有所帮助

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
}

对于我们使用android.opengl.GLSURFACHEVIEW的简单用例,我们解决了与您相同的问题,我们说,“如果手势中移动的距离小于某个阈值,请将其解释为单击”。我们使用了两个2D点之间的标准欧几里德距离=
sqrt((deltaX)^2+(deltaY)^2))
,其中
deltaX
deltaY
是用户运动姿态中移动距离的X和Y分量

更准确地说,让
(x1,y1)
成为用户手势“开始”的坐标,让
(x2,y2)
成为手势“结束”的坐标

然后,
deltaX=x2-x1
(或者它也可以是
x1-x2
,但符号与距离cz无关,我们将值平方),同样,对于
deltaY

根据这些增量,我们计算欧几里德距离,如果它小于阈值,用户可能希望它是一个点击,但由于设备的触摸斜率,它被归类为移动手势,而不是点击

在实现方面,是的,我们超越了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
    方法获得(请参阅)