Search code examples
androidandroid-listviewtouch-eventandroid-event

Detect touch event when onInterceptTouchEvent() used


I am asking this rather complex question hoping that i would get an idea from you.

Here is the thing: I have created a custom list view class, the one above:

public class FolderListView extends ListView {

    private float xDistance, yDistance, lastX, lastY;
    private int folder_index;
    private FolderViewInterface openFolder;

    // private boolean swiping = false;

    // If built programmatically
    public FolderListView(Context context) {
        super(context);
    }

    // This example uses this method since being built from XML
    public FolderListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // Build from XML layout
    public FolderListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

        case MotionEvent.ACTION_UP:
            // if (swiping == false) {

            //if (xDistance > yDistance)
            //  return false;
        //  else {
                folder_index = pointToPosition((int) lastX, (int) lastY);
            //  Toast.makeText(getContext(),
            //          "You pressed a folder with index: " + folder_index,
            //          Toast.LENGTH_SHORT).show();
        //  }
            HomeScreenFragment f = new HomeScreenFragment();
            openFolder = (FolderViewInterface) f;
            openFolder.onFolderOpened(folder_index);
            // }
            // swiping = false;
            break;

        case MotionEvent.ACTION_DOWN:
            // swiping = false;
            xDistance = yDistance = 0f;
            lastX = ev.getX();
            lastY = ev.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            // swiping = true;
            final float curX = ev.getX();
            final float curY = ev.getY();
            xDistance += Math.abs(curX - lastX);
            yDistance += Math.abs(curY - lastY);
            lastX = curX;
            lastY = curY;
            if (xDistance > yDistance)
                return false;
        }

        return super.onInterceptTouchEvent(ev);

    }

}

thing is here i am looking to properly detect the touch event. I want on touch to open the other fragment, but right now the fragment is opened both on touch and on swipe.

I have used the onInterceptTouchEvent because the elements of my list are viewpagers and they were not behaving properly when scrolling.

I need some kind of logic here to detect the swiping and not perform this part:

HomeScreenFragment f = new HomeScreenFragment();
            openFolder = (FolderViewInterface) f;
            openFolder.onFolderOpened(folder_index);

Only if the event is a touch event, not a swipe one.

Any kind of suggestion/help is highly appreciated, please let me know if you need any more details.

Thanks!


Solution

  • I am taking time 125 based on PRESSED_STATE_DURATION

    Try this

    //Declare as instance variables
    int oldX,oldY,newX,newY;
    //State the minimum distance of swipe that you forgive the user for ;)
    int distance = 10;
    int time = 125;
    boolean cancel = false;
    case MotionEvent.ACTION_DOWN:
    cancel = false;
    //Get x and y of touch
    oldX = ev.getX();
    oldY = ev.getY();
    startActionTimer();
    
    case MotionEvent.ACTION_MOVE:
    //Get x and y of touch
    newX = ev.getX();
    newY = ev.getY();
    
    case MotionEvent.ACTION_UP:
    cancel = true;
    
    private void startActionTimer(){
            //time is pressed state duration
              new CountDownTimer(time, time) {
                 public void onTick(long millisUntilFinished) {}
    
                 public void onFinish() {
                    //Time to do our action!!!
                    // please consider
                    if((Math.abs(newX - oldX )< distance) && (Math.abs(newY - oldY ) <distance)){
                        if(cancel == false){
                        // Now its a touch so do your action
                        }
                    }
                 }
              }.start();
         }
    

    NOTE: Please use all the variables as class variables(instance variables) to avoid problems. Because sometimes i get weird situations where values are not updated properly

    OR

    Why don't you try the gesture detection

    and override the onSingleTapUp method