onTouchListener、onTouchEvent、onClick区别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/alex01550/article/details/83585260

这里主要探讨Activity的onTouchEvent()、View的onTouch()、onTouchEvent()、onClick()之间的区别

测试代码如下:

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_touch);

        btnTest = findViewById(R.id.btn_test);

        btnTest.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        Log.e(TAG, "onTouch: ACTION_DOWN" );
                        break;

                    case MotionEvent.ACTION_MOVE:
                        Log.e(TAG, "onTouch: ACTION_MOVE" );
                        break;

                    case MotionEvent.ACTION_UP:
                        Log.e(TAG, "onTouch: ACTION_UP" );
                        break;
                }
                return false;
            }
        });

        btnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "onClick: ");
                Toast.makeText(ViewTouchActivity.this, "click!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.e(TAG, "onTouchEvent: ACTION_DOWN" );
                break;

            case MotionEvent.ACTION_MOVE:
                Log.e(TAG, "onTouchEvent: ACTION_MOVE" );
                break;

            case MotionEvent.ACTION_UP:
                Log.e(TAG, "onTouchEvent: ACTION_UP" );
                break;
        }
        // 返回值为true,false貌似都没有多大影响
        return super.onTouchEvent(event);
    }

其中的Button为自定义的button,代码如下:

public MyButton(Context context) {
        super(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.e(TAG, "onTouchEvent: ACTION_DOWN");
                break;

            case MotionEvent.ACTION_MOVE:
                Log.e(TAG, "onTouchEvent: ACTION_MOVE");
                break;

            case MotionEvent.ACTION_UP:
                Log.e(TAG, "onTouchEvent: ACTION_UP");
                break;
        }
        return super.onTouchEvent(event);
    }

主要看View的onTouchListener、onTouchEvent、onClick方法,activity的onTouchEvent方法

一、 activity的onTouchEvent方法

直接看源码:

 /**
     * Called when a touch screen event was not handled by any of the views
     * under it.  This is most useful to process touch events that happen
     * outside of your window bounds, where there is no view to receive it.
     *
     * @param event The touch screen event being processed.
     *
     * @return Return true if you have consumed the event, false if you haven't.
     * The default implementation always returns false.
     */
    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }

        return false;
    }

翻译:如果屏幕的触摸事件没有被他下边的view所处理,那么它将调用。通常用来处理发生在view触摸边界外边的触摸事件。  简单来说就是只要触摸屏幕,如果触摸的边界在view的触摸边界内,如果view处理了这个事件,那么该方法将不发生调用。如果view没有处理该事件,将由该方法处理;如果触摸的边界在view的触摸边界外(没有任何view来处理这个事件),将发生调用。

二、 view的setOnTouchListener方法

源码如下:

    /**
     * Interface definition for a callback to be invoked when a touch event is
     * dispatched to this view. The callback will be invoked before the touch
     * event is given to the view.
     */
    public interface OnTouchListener {
        /**
         * Called when a touch event is dispatched to a view. This allows listeners to
         * get a chance to respond before the target view.
         *
         * @param v The view the touch event has been dispatched to.
         * @param event The MotionEvent object containing full information about
         *        the event.
         * @return True if the listener has consumed the event, false otherwise.
         */
        boolean onTouch(View v, MotionEvent event);
    }

翻译:当触摸事件分发给该view时发生调用。回调将在触摸事件给该目标view之前调用。

返回值true表示消费了事件,false相反。

三、 view的onTouchEvent方法

源码如下:

 /**
     * Implement this method to handle touch screen motion events.
     * <p>
     * If this method is used to detect click actions, it is recommended that
     * the actions be performed by implementing and calling
     * {@link #performClick()}. This will ensure consistent system behavior,
     * including:
     * <ul>
     * <li>obeying click sound preferences
     * <li>dispatching OnClickListener calls
     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
     * accessibility features are enabled
     * </ul>
     *
     * @param event The motion event.
     * @return True if the event was handled, false otherwise.
     */
    public boolean onTouchEvent(MotionEvent event) {
        ...

         switch (action) {
                case MotionEvent.ACTION_UP:
                 ...
                 performClick();
                 ...
                 break;
        ...

    }

翻译:实现这个方法从而处理屏幕的触摸移动事件。如果事件被处理,返回结果为true;否则返回false。如果你想用这个方法监测点击事件,建议你去实现performClick方法,这将保证连贯的系统行为。

从源码也可以看到,在ACTION_UP事件中调用了performClick(),实际就是执行了onClick方法。

测试场景

onTouch返回值为false,其他为默认值,ACTION_MOVE个数不确定
* 10-31 15:11:08.104 20389-20389/com.rain.testeverything E/ViewTouchActivity: onTouch: ACTION_DOWN
* 10-31 15:11:08.104 20389-20389/com.rain.testeverything E/MyButton: onTouchEvent: ACTION_DOWN
* 10-31 15:11:08.153 20389-20389/com.rain.testeverything E/ViewTouchActivity: onTouch: ACTION_UP
* 10-31 15:11:08.153 20389-20389/com.rain.testeverything E/MyButton: onTouchEvent: ACTION_UP
onTouch返回值为true,同时设置的有点击事件,ACTION_MOVE个数不确定
* 10-31 15:05:26.027 15275-15275/com.rain.testeverything E/ViewTouchActivity: onTouch: ACTION_DOWN
* 10-31 15:05:26.081 15275-15275/com.rain.testeverything E/ViewTouchActivity: onTouch: ACTION_UP
onTouch返回值为false,View的onTouchEvent返回false,同时设置的有点击事件,ACTION_MOVE个数不确定
* 10-31 15:24:32.156 26667-26667/com.rain.testeverything E/ViewTouchActivity: onTouch: ACTION_DOWN
* 10-31 15:24:32.156 26667-26667/com.rain.testeverything E/MyButton: onTouchEvent: ACTION_DOWN
* 10-31 15:24:32.156 26667-26667/com.rain.testeverything E/ViewTouchActivity: onTouchEvent: ACTION_DOWN
* 10-31 15:24:32.198 26667-26667/com.rain.testeverything E/ViewTouchActivity: onTouchEvent: ACTION_MOVE
* 10-31 15:24:32.209 26667-26667/com.rain.testeverything E/ViewTouchActivity: onTouchEvent: ACTION_UP

结论

1. onTouch方法如果返回true,onTouchEvent方法将接收不到事件,onClick方法也不会调用;

2. onTouch方法如果返回false,onTouchEvent方法也返回false,即最终view不处理事件,那么将由activity的onTouchEvent

方法进行事件的处理;

3. activity的onTouchEvent方法,只有在任何的view都不处理事件的时候才发生调用。

猜你喜欢

转载自blog.csdn.net/alex01550/article/details/83585260