Reputation: 1017
I have a ListView in Android and I would like to have onTouchListeners for the row views and the parent ListView itself. I'd like to respond to single taps and long presses on the rows individually, but to flings on the ListView as a whole. (I can set the onFling method for each of the rows individually, but it's not robust, since the user can move his finger across rows.) I'm able to successfully set an onTouchListener for the rows and the ListView separately, but when I set both, the ListView listener never triggers - only the row listeners. This is the case whether I return true or false in the methods of the row listener. Does anybody know how to trigger onTouchListeners for both a view and its parent, given that they occupy the same pixels on the screen?
The relevant code for the ListView:
In the activity onCreate method:
mListViewDetector = new GestureDetector(new ListViewGestureListener());
mListViewListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return mListViewDetector.onTouchEvent(event);
}
};
mListView = getListView();
mListView.setOnTouchListener(mListViewListener);
And the custom GestureListener class (defined as a nested class in the activity):
class ListViewGestureListener extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i("ListViewGestureDetector","onFling");
return false;
}
}
The relevant code for the individual rows in the Listview:
In the bindView method of the the adapter class:
TextView textView;
textView.setOnTouchListener(new ListsTextViewOnTouchListener());
And the custom onTouchListener class (defined as a nested class in the adapter class):
class ItemsTextViewOnTouchListener implements OnTouchListener {
public boolean onTouch (View v, MotionEvent event){
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
//stuff
return false;
case MotionEvent.ACTION_CANCEL:
//stuff
return false;
default:
break;
}
return false;
}
}
Upvotes: 2
Views: 1069
Reputation: 13015
Pvans,
The answer is a little tricksy, but that capability is built in. onTouchEvent()
handles the TouchEvent for whichever object(s) it is a listener for. There are then two options for accomplishing what you would like.
1) You can override onInterceptTouchEvent()
on the parent View and handle your fling there. I find that this works great for large Views with smaller child Views. I do not prefer this method for Lists (to be frank). onInterceptTouchEvent()
is awesome at taking the Touch away from the children, but if you do this, you would have to handle both flinging left/right and scrolling horizontally.
2) You can also create a GestureDetector
that is actually an invisible overlay (sort of). If you forward your onTouchEvents to it, you will still get the desired behavior, and you don't have to worry about handling your scrolling manually. In this case, you simply send the TouchEvent to the Detector and if it returns true, your List does nothing and your OnFling does the work. If it returns false, it wasn't handled so it must belong to the List or one of its children.
Hope this helps, FuzzicalLogic
Upvotes: 1