Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gesture Listener onFling Not Acting Consistant

Update: See bounty for expanded question.

I have a GestureDetector setup on a ListView. The ListView is an entire fragment that comes from side of window and overlays another fragment partially. I want to give user ability to swipe it close (i.e. Wunderlist is a great example of this function on right side).

Here is my setup:

    gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {

            if (gestureDetector.onTouchEvent(event)) {
                return true;
            }

            return false;
        }
    };
    listView.setOnTouchListener(gestureListener); 

The Listener itself:

public class GestureListener extends SimpleOnGestureListener {

        private static final int SWIPE_MIN_DISTANCE = 180;
        private static final int SWIPE_THRESHOLD_VELOCITY = 50;

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {

            try {
                if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                        && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

                    FragmentManager fma = getActivity()
                            .getSupportFragmentManager();



                    FragmentManager fm = getFragmentManager();
                    FragmentTransaction t = fm.beginTransaction();

                    SherlockListFragment mFrag = new RateReviewFragment();

                    t.add(R.id.main_frag, mFrag);
                    t.setCustomAnimations(R.anim.animation_enter,
                            R.anim.animation_leave);
                    t.remove(mFrag);
                    t.commit();

                }
                return false;
            } catch (Exception e) {

            }
            return false;
        }





        @Override
        public void onLongPress(MotionEvent e) {

            // edited out; this opens up a context menu
        }

    }

Sometimes, when the ListView scrolls to the bottom (or list scrolling is interrupted with clicks on a list row) the GestureListener simply stops ... listening. Swiping will not work. You have to scroll back to top to get it to work again.

If anyone can help me isolate these issues I would be grateful!

UPDATE : Only one issue remains, "the listener stops listening"

UPDATE TWO: I may have figured out what is CAUSING this; just dont know the fix:

I have found something out after logging my actions; The lower I get in the list (and the more I interact with it), the measurements are not consistent. For example, if I move my finger a centimeter left and right - at very top of list, it will say I moved, for example, 200 pixels. But when I have the problem stated above, it is far lower, maybe 50, for the SAME 1 centimeter distance. So the window doesn't close because it's not meeting my if conditions.

Sidenote: I have stated more than once, the problem is when "interacting with the list". This means: If I quickly scroll from top to bottom; no issue; but If I slowly work my way down, perhaps tapping on the screen, scrolling on and off, clicking buttons on the listView, some of which open a new activity (and then come back to same position), this is "interacting" with".

like image 372
TheLettuceMaster Avatar asked Jun 06 '13 20:06

TheLettuceMaster


2 Answers

try this,

    gestureDetector = new GestureDetector(getActivity(),
            new GestureListener());
    View.OnTouchListener gestureListener = new View.OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {
           listView.onTouchEvent(event);
           gestureDetector.onTouchEvent(event);

            return true;
        }
    };
    listView.setOnTouchListener(gestureListener);

and make the following change

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
  return true;
}

EDIT: I saw the app wunderlist, if u want to simulate that functionality try out this approach,

Use onInterceptTouch for the root layout (of which listView is a child of), inside this method u have to check whteher the user has swiped or not like the following,

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
  if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    if(/* Check your condition here */) { 
      // User has swiped 
      return true;
    }
  }

  return false; // return false so that the event will be passed to child views.
}

for more info Android onInterceptTouchEvent

like image 59
AjOnFire Avatar answered Nov 20 '22 01:11

AjOnFire


change the onTouch this way:

@Override
public boolean onTouch(View arg0, MotionEvent arg1) {
     boolean consumed = gestureDetector.onTouchEvent(event);
     if (event.getAction() == MotionEvent.ACTION_MOVE) {
                return false;
     }

    return consumed;
}
like image 2
Blackbelt Avatar answered Nov 20 '22 00:11

Blackbelt