自定义View - 20.View的Touch事件分发

2018-07-04  本文已影响12人  zsj1225

看下面代码会怎么打印?

public class TouchView extends View {
    public TouchView(Context context) {
        super(context);
    }

    public TouchView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public TouchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("ZsjTAG", "onTouchEvent "+event.getAction());
        return super.onTouchEvent(event);
    }
}
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTouchView = (TouchView) findViewById(R.id.touchView);
        mTouchView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d("ZsjTAG", "onTouch " + event.getAction());
                return false;
            }
        });

        mTouchView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("ZsjTAG", "onClick ");
            }
        });
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zsj.taglayout.MainActivity">


    <com.zsj.taglayout.TouchView
        android:id="@+id/touchView"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:background="@color/colorAccent"
        />

</RelativeLayout>

1.上面代码的现象:

1.1 现象 OnTouchListener OnTouch OnClickListener 三个都有的情况下 前提是OnTouchListener 返回false

OnTouchListener.DOWN -> OnTouch.DOWN -> OnTouchListener.MOVE -> OnTouch.MOVE -> OnTouchListener.UP-> OnTouch.UP-> OnClickListener

1.2 现象 OnTouchListener OnTouch OnClickListener 三个都有的情况下 前提是OnTouchListener 返回true

OnTouchListener.DOWN -> OnTouchListener.MOVE -> OnTouchListener.UP

1.2 现象 OnTouch OnClickListener 前提是 OnTouch 返回true

OnTouch .DOWN -> OnTouch .MOVE -> OnTouch.UP 不会执行onClick

为什么会是这样的现象?下面分析源码.

2. View 与 Touch 相关的有两个非常重要的方法

2.1 dispatchTouchEvent 事件分发

2.2 onTouchEvent方法(一般都会被我们复写)

看dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent event) {
    boolean result = false;

    //ListenerInfo  存放了我们所有Listener的信息,如OnTouchListener,OnClickListener
    ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnTouchListener != null //是否设置了onTouchListener,如果设置onTouchListener,接着判断View是不是enable(可用)
          && (mViewFlags & ENABLED_MASK) == ENABLED //是否是enable,如果是ture,回调onTouch方法
          && li.mOnTouchListener.onTouch(this, event)) { //onTouch返回的false还是ture.如果是false,result则是false,如果是true,result则是true.
        result = true;
    }

    if (!result && onTouchEvent(event)) { //如果result是false.就会执行onTouchEvent.如果result是true就不会执行onTouchEvent()
        result = true;
    }
    return result;
}

到目前为止没有看到点击事件?

看一下onTouchEvent方法

public boolean onTouchEvent(MotionEvent event) {
    switch (action) {
        case MotionEvent.ACTION_UP:
            performClick();
    }
}

public boolean performClick() {
    final boolean result;
    final ListenerInfo li = mListenerInfo;
    if (li != null && li.mOnClickListener != null) {
        //在这里调用onClick点击事件.
        li.mOnClickListener.onClick(this);
        result = true;
    } else {
        result = false;
    }
    return result;
}

相信源码看到这里.上面的现象你分析出为什么会如此打印.

上一篇 下一篇

猜你喜欢

热点阅读