前言:
我们根据自定义MyButton按钮,给这个按钮设置监听事件,通过输出日志了解事件分发。
一、MyButton类
public class MyButton extends AppCompatButton { 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); } //处理触摸事件的分发 是从dispatchTouchEvent开始的 @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.e("dispatchTouchEvent", "---dispatchTouchEvent--- " ); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.e("MyButton", "---onTouchEvent---" ); break; } return super.onTouchEvent(event); } }
之后写xml布局文件,这个就不再给出代码。
最后在EventActivity2中设置按钮的监听事件。
public class EventActivity2 extends AppCompatActivity { private static final String TAG = "EventActivity2"; private MyButton my_btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_event2); my_btn = findViewById(R.id.my_btn); my_btn.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.e(TAG, "onTouch " ); break; } return false; } }); my_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.e(TAG, "onClick: " ); } }); } }
我们点击按钮之后,输出日志为:
分析:
触摸事件的分发,是从dispatchTouchEvent()开始的,所以先处理dispatchTouchEvent(),这个方法。
之后开始处理按钮的监听事件setOnTouchListener,按下的这个动作。
执行之后,开始执行MyButton控件中的onTouchEvent()这个回调方法。
之后又执行了dispatchTouchEvent(),是因为当用户抬起时,也要从触摸事件的入口dispatchTouchEvent()开始,之后我们执行onClick点击事件。
那么我们View事件的分发,就是从
dispatchTouchEvent(触摸事件入口)–>setOnTouchListener(触摸事件监听器)–>onTouchEvent(触摸事件的回调方法)。
其中onClick和onLongClick是来自onTouchEvent()的处理。
注意
:当我们手指按下按钮的时候,执行ACTION_DOWN这个动作,之后会延时100毫秒,检查有没有执行到ACTION_UP这个环节,如果没有执行到,会再发出一个延时400毫秒,检查有没有执行到ACTION_UP这个环节。
就是说长按时间最起码要按住控件500毫秒以上,如果小于500毫秒则为点击事件。
前提: 我们在按下的时候,会在屏幕上面进行ACTION_MOVE进行滑动,如果滑出这个控件,我们的onClick和onLongClick会被remove移除掉。
onLongClickListener长按事件的返回值为boolean ,如果返回值为true则说明此事件被消费掉了,不会再执行onClick点击事件了,如果返回为false,说明此事件没有被消费掉,会继续执行点击事件。
View的事件分发:
ViewGroup的事件分发: