androidswipegesture-recognitiononfling

How to ignore overlying views and detect onFling (onSwipe)?


I have a view with a lot of Childs. What I need is to implement reaction on Swipe or on Fling moves. Problem is that it only really works if I remove all Childs, otherwise Child views on the top of the main layout block my attempts to swipe.

I tried both adding onSwipeListener to the main layout and adding GestureListener to the whole activity with the same success.

My current (non-working) solution looks like:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_schedule);

        main_layout = findViewById(R.id.schedule_main_view);
        Animation fadeInAnimation = AnimationUtils.loadAnimation(this, R.anim.fade);
        main_layout.startAnimation(fadeInAnimation);

        GestureDetector.SimpleOnGestureListener simpleOnGestureListener =
                new GestureDetector.SimpleOnGestureListener() {
                    @Override
                    public boolean onDown(MotionEvent event) {
                        return true;
                    }

                    @Override
                    public boolean onFling(MotionEvent event1, MotionEvent event2,
                                           float velocityX, float velocityY) {
                        Log.d(null,"Fling");
                        int dx = (int) (event2.getX() - event1.getX());
                        // don't accept the fling if it's too short
                        // as it may conflict with a button push
                        if (Math.abs(dx) > 20
                                && Math.abs(velocityX) > Math.abs(velocityY)) {
                            if (velocityX > 0) {
                                Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
                                Log.d(DEBUG_TAG, "onFling To Right");
                            } else {
                                Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
                                Log.d(DEBUG_TAG, "onFling To Left");
                            }
                            return true;
                        } else {
                            return false;
                        }
                    }
                };

        shift = getIntent().getIntExtra(WEEK_SHIFT, CURRENT_WEEK);
        mDetector = new GestureDetectorCompat(this,simpleOnGestureListener);
        unDimScreen();
        setupWeek();
    }

To repeat: if the activity is in the state when there are no child views on top, it works as intended.

So the question is: what I can do to make activity fetch gestures ignoring the overlying views?


Solution

  • The problem is child views getting touch events and not giving it to the parent. If you are not using on overlying views clickable events, you can turn off on that views clickable property like view.setClickable(false); ... Then all click events will go it's parent view. If it doesn't works, you can define on touch listener on every overlying views like this:

    view.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            return false;
        }
    });
    

    UPD: Here another (right) solution of this problem: https://developer.android.com/training/gestures/viewgroup.html#delegate