Android解決OnClick和OnTouch衝突

        在商顯懸浮按鈕開發過程中遇到的問題,懸浮按鈕即要實現隨手指移動而移動(onTouch),也要實現點擊事件(onClick事件),這裏會遇到一個問題,在onTouch方法return false的時候,在滑動過程中擡起的時候會觸發 MotionEvent.ACTION_UP 事件,同時也會觸發onClick事件,如果onTouch方法return true,則view的onClick事件不會執行。
        通過查看View的源碼,View的listener都存在一個靜態內部類裏面,

 static class ListenerInfo {
        /**
         * Listener used to dispatch focus change events.
         * This field should be made private, so it is hidden from the SDK.
         * {@hide}
         */
        protected OnFocusChangeListener mOnFocusChangeListener;

        /**
         * Listeners for layout change events.
         */
        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;

        protected OnScrollChangeListener mOnScrollChangeListener;

        /**
         * Listeners for attach events.
         */
        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;

        /**
         * Listener used to dispatch click events.
         * This field should be made private, so it is hidden from the SDK.
         * {@hide}
         */
        public OnClickListener mOnClickListener;

        /**
         * Listener used to dispatch long click events.
         * This field should be made private, so it is hidden from the SDK.
         * {@hide}
         */
        protected OnLongClickListener mOnLongClickListener;

        /**
         * Listener used to dispatch context click events. This field should be made private, so it
         * is hidden from the SDK.
         * {@hide}
         */
        protected OnContextClickListener mOnContextClickListener;

        /**
         * Listener used to build the context menu.
         * This field should be made private, so it is hidden from the SDK.
         * {@hide}
         */
        protected OnCreateContextMenuListener mOnCreateContextMenuListener;

        private OnKeyListener mOnKeyListener;

        private OnTouchListener mOnTouchListener;

        private OnHoverListener mOnHoverListener;

        private OnGenericMotionListener mOnGenericMotionListener;

        private OnDragListener mOnDragListener;

        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;

        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
    }

    ListenerInfo mListenerInfo;

通過反射獲取mListenerInfo實例,再獲取mListenerInfo裏面的mOnClickListener,最後調用mOnClickListener.onClick()方法即可,修改後的onTouch代碼如下
 

 button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN: {
                        Log.i("mandroid.cn", "button按下");
                        //記錄按下時的位置
                        x = motionEvent.getRawX();
                        y = motionEvent.getRawY();
                        break;
                    }
                    case MotionEvent.ACTION_MOVE: {
                        Log.i("mandroid.cn", "button移動");
                        break;
                    }
                    case MotionEvent.ACTION_UP: {
                        //檢測移動的距離,如果很微小可以認爲是點擊事件
                        if (Math.abs(motionEvent.getRawX() - x) < 10 && Math.abs(motionEvent.getRawY() - y) < 10) {
                            try {
                                Field field = View.class.getDeclaredField("mListenerInfo");
                                field.setAccessible(true);
                                Object object = field.get(view);
                                field = object.getClass().getDeclaredField("mOnClickListener");
                                field.setAccessible(true);
                                object = field.get(object);
                                if (object != null && object instanceof View.OnClickListener) {
                                    ((View.OnClickListener) object).onClick(view);
                                }
                            } catch (Exception e) {

                            }
                        } else {
                            Log.i("mandroid.cn", "button已移動");
                        }
                        break;
                    }
                }
                return true;
            }
        });

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章