Android事件传递机制
Android事件构成
在Android中,所有的事件都由如下三个部分作为基础:
- 按下(ACTION_DOWN)
- 移动(ACTION_MOVE)
- 抬起(ACTION_UP)
View.java
public boolean dispatchTouchEvent(MotionEvent event) public boolean onTouchEvent(MotionEvent event)
ViewGroup.java
public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event) public boolean onInterceptTouchEvent(MotionEvent event)
在Android中,所有的事件都是从开始经过传递到完成事件的消费,这些方法的返回值就决定了某一事件是否是继续往下传,还是被拦截了,或是被消费了。
dispatchTouchEvent方法用于事件的分发,Android中所有的事件都必须经过这个方法的分发,然后决定是自身消费当前事件还是继续往下分发给子控件处理。返回true表示不继续分发,事件没有被消费。返回false则继续往下分发,如果是ViewGroup则分发给onInterceptTouchEvent进行判断是否拦截该事件。onTouchEvent方法用于事件的处理,返回true表示消费处理当前事件,返回false则不处理,交给子控件进行继续分发。onInterceptTouchEvent是ViewGroup中才有的方法,View中没有,它的作用是负责事件的拦截,返回true的时候表示拦截当前事件,不继续往下分发,交给自身的onTouchEvent进行处理。返回false则不拦截,继续往下传。这是ViewGroup特有的方法,因为ViewGroup中可能还有子View,而在Android中View中是不能再包含子View的(iOS可以)。
事件流程图:
总结
- Android中事件传递按照从上到下进行层级传递,事件处理从Activity开始到ViewGroup再到View。
- 事件传递方法包括
dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent,其中前两个是View和ViewGroup都有的,最后一个是只有ViewGroup才有的方法。这三个方法的作用分别是负责事件分发、事件处理、事件拦截。 - onTouch事件要先于onClick事件执行,onTouch在事件分发方法dispatchTouchEvent中调用,而onClick在事件处理方法onTouchEvent中被调用,onTouchEvent要后于dispatchTouchEvent方法的调用。
- 若view的onTouch中的方法返回true,则不会执行view的onTouchEvent,则在view中也不会执行onclick方法。
- 若view 和viewgroup的ontouch方法都为true,则都不会触发onTouchEvent,则不会执行onclick方法。
public class MainActivity extends Activity { private RTButton button; private RTLayout rtlayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (RTButton) this.findViewById(R.id.btn); rtlayout = (RTLayout)findViewById(R.id.myLayout); button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTButton---onTouch---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTButton---onTouch---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTButton---onTouch---UP"); break; default: break; } return false; } }); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("RTButton clicked!"); } }); rtlayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTLayout---onTouch---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTLayout---onTouch---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTLayout---onTouch---UP"); break; default: break; } return true; } }); rtlayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { System.out.println("RTLayout clicked!"); } }); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("Activity---dispatchTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("Activity---dispatchTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("Activity---dispatchTouchEvent---UP"); break; default: break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("Activity---onTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("Activity---onTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("Activity---onTouchEvent---UP"); break; default: break; } return super.onTouchEvent(event); } }
public class RTButton extends Button { public RTButton(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTButton---dispatchTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTButton---dispatchTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTButton---dispatchTouchEvent---UP"); break; default: break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTButton---onTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTButton---onTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTButton---onTouchEvent---UP"); break; default: break; } return super.onTouchEvent(event); } }
public class RTLayout extends LinearLayout { public RTLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTLayout---dispatchTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTLayout---dispatchTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTLayout---dispatchTouchEvent---UP"); break; default: break; } return super.dispatchTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTLayout---onInterceptTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTLayout---onInterceptTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTLayout---onInterceptTouchEvent---UP"); break; default: break; } return super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: System.out.println("RTLayout---onTouchEvent---DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("RTLayout---onTouchEvent---MOVE"); break; case MotionEvent.ACTION_UP: System.out.println("RTLayout---onTouchEvent---UP"); break; default: break; } return super.onTouchEvent(event); } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.jiudao.touch.event.RTLayout android:id="@+id/myLayout" android:layout_width="match_parent" android:layout_height="match_parent" > <com.jiudao.touch.event.RTButton android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Button" /> </com.jiudao.touch.event.RTLayout> </LinearLayout>
转载自:http://orgcent.com/android-touch-event-mechanism/
浙公网安备 33010602011771号