文章共分兩篇金闽,會詳細介紹Activity纯露,View,ViewGroup三者的觸摸事件傳遞機制代芜。一次完整的事件傳遞主要包括三個階段埠褪,分別是事件的分發(fā),攔截和消費。
1.1 觸摸事件的類型
觸摸事件對應的MotionEvent類钞速,事件的類型主要有如下三種
? ? ACTION_DOWN:用戶手指按下的操作,一個按下標志著一個觸摸事件的開始贷掖。
? ? ACTION_MOVE:用戶手指按下在抬起之前,移動的距離超過一定的值渴语,會被判定為? ? ? ? ?????????????????????????????????ACTION_MOVE操作 一般手苹威,指的輕微移動都會觸發(fā)一系列的移動事件。
? ? ACTION_UP:用戶手指離開屏幕的操作驾凶,一次抬起操作標志著一次觸摸事件的結(jié)束牙甫。
1.2 事件傳遞的三個階段
? ? 分發(fā)(Dispatch):事件的分發(fā)對應這dispatchTouchEvent方法,在Android系統(tǒng)中所有的觸摸事件都是通過這個方法分發(fā)的狭郑。
? ? 攔截(Intercept):事件的攔截對應著onInterceptTouchEvent方法腹暖,這個方法只在ViewGroup及其子類中存在。
? ? 消費(Consume):事件的消費對應著onTouchEvent方法翰萨。????
? ? 在Android系統(tǒng)中脏答,擁有事件傳遞能力的類有以下三種:
? ? ? ? Activity:擁有dispatchTouchEvent和onTouchEvent兩個方法。
? ? ? ? ViewGroup:擁有dispatchTouchEvent亩鬼,onInterceptTouchEvent和onTouchEvent兩個方法殖告。
? ? ? ? View:擁有dispatchTouchEvent和onTouchEvent兩個方法。
? ? 1.3 View事件的傳遞機制
? ? ? ?這里所說的View指ViewGroup以外的View雳锋,如TextView黄绩,Button,ImageView等玷过。
? ??public class MyTextView extends AppCompatTextView {
? ? private static final String TAG = MyTextView.class.getSimpleName();
? ? public MyTextView(Context context) {
? ? ? ? super(context);
? ? }
? ? public MyTextView(Context context, @Nullable AttributeSet attrs) {
? ? ? ? super(context, attrs);
? ? }
? ? public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
? ? ? ? super(context, attrs, defStyleAttr);
? ? }
? ? @Override
? ? public boolean dispatchTouchEvent(MotionEvent event) {
? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_DOWN");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_MOVE");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_UP");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? return super.dispatchTouchEvent(event);
? ? }
? ? @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;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return super.onTouchEvent(event);
? ? }
}
同時定義MainActivity用來展示MyTextView爽丹,在這個Activity中,我們對MyTextView設置了點擊(onClick)觸摸(onTouch)監(jiān)聽辛蚊。
public class MainActivity extends AppCompatActivity implements View.OnTouchListener , View.OnClickListener {
? ? private static final String TAG = MainActivity.class.getSimpleName();
? ? private TextView textView;
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_main);
? ? ? ? textView = findViewById(R.id.tv);
? ? ? ? textView.setOnTouchListener(this);
? ? ? ? textView.setOnClickListener(this);
? ? }
? ? @Override
? ? public boolean dispatchTouchEvent(MotionEvent event) {
? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_DOWN");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_MOVE");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? Log.e(TAG,"dispatchTouchEvent ACTION_UP");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return super.dispatchTouchEvent(event);
? ? }
? ? @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;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return super.onTouchEvent(event);
? ? }
? ? @Override
? ? public boolean onTouch(View v, MotionEvent event) {
? ? ? ? switch (event.getAction()) {
? ? ? ? ? ? case MotionEvent.ACTION_DOWN:
? ? ? ? ? ? ? ? Log.e(TAG,"MyTextView onTouch ACTION_DOWN");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_MOVE:
? ? ? ? ? ? ? ? Log.e(TAG,"MyTextView onTouchEvent ACTION_MOVE");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? case MotionEvent.ACTION_UP:
? ? ? ? ? ? ? ? Log.e(TAG,"MyTextView onTouchEvent ACTION_UP");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return false;
? ? }
? ? @Override
? ? public void onClick(View v) {
? ? ? ? if (v.getId() == R.id.tv) {
? ? ? ? ? ? Log.e(TAG,"MyTextView onClick");
? ? ? ? }
? ? }
}
運行上面的代碼粤蝎,點擊MyTextView,打印日志袋马。
2019-10-29 16:26:55.547 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MyTextView: dispatchTouchEvent ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onTouch ACTION_DOWN
2019-10-29 16:26:55.548 14052-14052/com.hzy.mydemo E/MyTextView: onTouchEvent ACTION_DOWN
2019-10-29 16:26:55.566 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTIO
2019-10-29 16:26:55.645 14052-14052/com.hzy.mydemo E/MainActivity: dispatchTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MyTextView: dispatchTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onTouchEvent ACTION_UP
2019-10-29 16:26:55.646 14052-14052/com.hzy.mydemo E/MyTextView: onTouchEvent ACTION_UP
2019-10-29 16:26:55.648 14052-14052/com.hzy.mydemo E/MainActivity: MyTextView onClick
不同的返回方式傳遞流程相差甚遠初澎,請看流程圖