Passing touch events to the parent view

后端 未结 9 1073
情书的邮戳
情书的邮戳 2020-11-27 05:25

I have a custom ViewSwitcher in which I implemented touch events so I am able to scroll through screens using the touchscreen.

My layout hierarchy looks

相关标签:
9条回答
  • 2020-11-27 05:56

    It was necessary to handle the touch in the TextView in the parent view with the autoLink = "three" Did so:

    private LinearLayout mParentView;
    private TextView mTextView;
    private View.OnTouchListener mParentListener = new OnTouchListener() {
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            ......
            return false;
        }
    };
    mParentView.setOnTouchListener(mParentListener);
    
    mTextView.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            mParentListener.onTouch(mParentView, event);
            return false;
        }
    };
    
    0 讨论(0)
  • 2020-11-27 06:03

    You could also insert a call to handle the touchevent in dispatchTouchEvent, but in this case you have also to override onTouchEvent to return true, otherwise only the first MotionEvent DOWN of the gesture will be passed.

    This is the touchable wrapper container:

    <?xml version="1.0" encoding="utf-8"?>
    <view xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.example.myapp.FragmentContainer$TouchableWrapper" />
    

    And the class:

    public static class TouchableWrapper extends FrameLayout {
        private GestureDetector gestureDetector;
        public void setGestureDetector(GestureDetector gestureDetector) {
            this.gestureDetector = gestureDetector;
        }
    
        // these constructors for the XML inflater
        public TouchableWrapper(Context context) {
            super(context);
        }
        public TouchableWrapper(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        public TouchableWrapper(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {
            Log.d(TAG, "onInterceptTouchEvent " + event.toString());
            return false; // true for intercept, false è default and pass on to children View
        }
        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            Log.d(TAG, "dispatchTouchEvent " + event.toString());
            gestureDetector.onTouchEvent(event);
            return super.dispatchTouchEvent(event);
        }
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            Log.d(TAG, "onTouchEvent " + event.toString());
            return true; //return super.onTouchEvent(event); 
        }
    }
    

    This is the GestureDetector reference:

    private GestureDetector gestureDetector;
    

    This the GestureListener:

    private GestureDetector.SimpleOnGestureListener sOGL = new GestureDetector.SimpleOnGestureListener() {
        private static final int SWIPE_THRESHOLD = 100;
        private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
    
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            boolean result = false;
            try {
                float diffY = e2.getY() - e1.getY();
                float diffX = e2.getX() - e1.getX();
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            goToRight(); // onSwipeRight();
                        } else {
                            goToLeft(); // onSwipeLeft();
                        }
                    }
                    result = true;
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        // onSwipeBottom();
                    } else {
                        // onSwipeTop();
                    }
                }
                result = true;
    
            } catch (Exception exception) {
                exception.printStackTrace();
            }
            return result; // return false indicate event not handled
        }
    };
    

    Ant this to load the touchable container fragment and a contained fragment:

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d(TAG, "onCreateView()");
        View view = inflater.inflate(R.layout.fragmentcontainer, container, false);
    
        gestureDetector = new GestureDetector(view.getContext(), sOGL);
        ((FragmentContainer.TouchableWrapper) view).setGestureDetector(gestureDetector);
    
        FragmentManager fm = this.getFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.pager, frag).commit();
    
        return view;
    }
    
    0 讨论(0)
  • 2020-11-27 06:04

    The simplest way to pass child view's TouchEvent to parent view is by adding this to child view:

    @Override
    public boolean onTouchEvent(MotionEvent event) { 
        super.onTouchEvent(event);
        return false;
    }
    
    0 讨论(0)
提交回复
热议问题