I created a custom component with both an onTouchListener and a gesture detector, I put the custom component in MainActivity's xml file which also has both onTouchEvent and a gesture detector. I want to detect single taps on the custom component and long presses on MainActivity, but it seems somehow the touch listeners interact and the single taps never get detected.
MainActivity.java:
public class MainActivity extends ActionBarActivity {
private GestureDetector detector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
detector = new GestureDetector(this, new LongPressDetector());
}
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
int action = event.getActionMasked();
switch (action){
case MotionEvent.ACTION_DOWN:{
Log.d("TouchEvent", "Action_Down at MainActivity.java");
break;
}
}
return super.onTouchEvent(event);
}
private class LongPressDetector extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onDown(MotionEvent e) {
Log.d("TouchEvent", "onDown at MainActivity.java");
return super.onDown(e);
}
@Override
public void onLongPress(MotionEvent e) {
Log.d("TouchEvent", "onLongPress at MainActivity.java");
super.onLongPress(e);
}
}
}
CustomView.java:
public class CustomView extends RelativeLayout {
private GestureDetector detector;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context c){
LayoutInflater layoutInflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater.inflate(R.layout.customview, this);
detector = new GestureDetector(c, new TapDetector());
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
detector.onTouchEvent(event);
int action = event.getActionMasked();
switch (action){
case MotionEvent.ACTION_DOWN:{
Log.d("TouchEvent", "Action_Down at CustomView.java");
break;
}
}
return false;
}
});
}
private class TapDetector extends GestureDetector.SimpleOnGestureListener{
@Override
public boolean onDown(MotionEvent e) {
Log.d("TouchEvent", "onDown at CustomView.java");
return super.onDown(e);
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.d("TouchEvent", "onSingleTapUp at CustomView.java");
return super.onSingleTapUp(e);
}
}
}
public boolean onSingleTapUp (MotionEvent e) Notified when a tap occurs with the up MotionEvent that triggered it. Parameters. e. MotionEvent : This value cannot be null .
If you are going to respond to a tap up you also need to return true from onDown, the default will return false (I'm guessing here).
At least for me anyway, I wasn't getting onSingleTapUp
called for my code until I made sure onDown
returned true.
@Override
public boolean onDown(MotionEvent e) {
return true;
}
I've seen other frameworks where 'up' events are only delivered if 'down' events are accepted, so I assumed that was what was happening here.
there is no need for guessing (@alexndr) !!! look at sources
if u extends GestureDetector.SimpleOnGestureListener call to super.onDown(event)
public boolean onDown(MotionEvent e) {
return false;
}
will return false but if u implement gesture detector listener then there is no super !
public class GestureDetector {
/**
* The listener that is used to notify when gestures occur.
* If you want to listen for all the different gestures then implement
* this interface. If you only want to listen for a subset it might
* be easier to extend {@link SimpleOnGestureListener}.
*/
public interface OnGestureListener {
/**
* Notified when a tap occurs with the down {@link MotionEvent}
* that triggered it. This will be triggered immediately for
* every down event. All other events should be preceded by this.
*
* @param e The down motion event.
*/
boolean onDown(MotionEvent e);
ps. rule is simple:
if EVENT is CONSUMED RETURN TRUE if NOT RETURN FALSE
You just need return true in your onTouchEvent(MotionEvent event)
.
Somewhat like this:
@Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
int action = event.getActionMasked();
switch (action){
case MotionEvent.ACTION_DOWN:{
Log.d("TouchEvent", "Action_Down at MainActivity.java");
break;
}
}
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With