Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increase touch slop in Android button

We have an Android app that is meant to be mounted on the dash of a vehicle that is operating in rough terrain, so everything is really shaky. We've found that making a single tap on the screen in this kind of situation is difficult, as the taps are often interpreted as small drags.

What I need is for touch events that have a little wiggle before the finger comes up to be interpreted as clicks, not drags. I've been doing some reading into the way the 'touch slop' works in Android and I can see that they already account for this. All I really need to understand is how to increase the 'touch slop' for a subclass of an Android button widget.

Is this possible in just a couple of lines of code? Or do I need to do my own implementations of onInterceptTouchEvent and 'onTouchEvent`? If the latter, can anyone give me some direction on how this would work?

like image 810
Mick Byrne Avatar asked Oct 22 '15 03:10

Mick Byrne


1 Answers

Here is what I did, hope that help you guys.

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
}
like image 89
NamNH Avatar answered Nov 06 '22 23:11

NamNH