Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 控件的觸摸事件傳遞與處理

Android 控件的觸摸事件傳遞與處理

編輯:關於Android編程

了解Android控件的觸摸事件傳遞與處理對我們日常開發中自定義控件和觸摸事件沖突解決有重大意義。Android控件的觸摸事件傳遞和處理主要有以下幾個方法,下面一一介紹。

一、與觸摸事件有關的幾個方法

boolean dispatchTouchEvent(MotionEvent ev);
接收到觸摸事件時,是否分發事件到下面的View
返回true:分發觸摸事件
返回false:不分發,下面的View就拿不到觸摸事件 boolean onInterceptTouchEvent(MotionEvent ev);
接收到觸摸事件時,是否攔截事件
返回true:攔截,則調用onTouchEvent方法處理事件
返回false:不攔截,事件繼續往子View傳
boolean onTouchEvent(MotionEvent ev);
是否響應事件
返回true:響應
返回false:不響應
boolean onTouch(View v, MotionEvent event);
是否響應事件,當View調用了setOnTouchListener方法設置了觸摸監聽器,則事件響應的時候先調用onTouch方法
返回true:響應,則onTouchEvent方法不執行
返回false:不響應,並調用onTouchEvent方法
void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
請求父控件是否不攔截事件
返回true:不允許父控件的onInterceptTouchEvent調用
返回false:允許調用


二、擁有這些方法的類

父類 子類 擁有的方法 Activity Activity dispatchTouchEvent、onTouchEvent
ViewGroup RelativeLayout, LinearLayout... dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent、requestDisallowInterceptTouchEvent View Button、TextView... dispatchTouchEvent、onTouchEvent


三、事件處理規則

觸摸事件是從Activity分發(只是分發,還沒有處理)到父控件,父控件先判斷是否攔截,如果不攔截事件,則繼續分發到子控件,然後一直往下分發。但處理就剛好相反,由子控件先處理事件,如果子控件沒有處理事件,則交給到父控件處理,一直往上處理,直到哪個控件處理了觸摸事件,就事件處理就到此結束。

1.當用戶觸摸屏幕的時候,從按下到移動,最後到抬起,會依次產生ACTION_DOWN、ACTION_MOVE、ACTION_UP三種觸摸事件,事件先傳到Activity,然後Activity調用分發事件方法dispatchTouchEvent,如果返回true,則事件就會傳給Activity的第一個父控件。

2.父控件拿到事件之後,也會調用分發事件方法dispatchTouchEvent,如果返回true,則繼續調用攔截方法onInterceptTouchEvent,如果返回true,則父控件攔截了事件,並調用父控件的onTouchEvent方法,下面的子控件就不會再響應onTouchEvent,onTouch的方法。

3.子控件拿到事件之後,先判斷是否設置了OnTouchListener, 如果設置了,則調用OnTouchListener的onTouch方法,如果返回true,事件已經處理到此結束,則跳過onTouchEvent方法,否則調用onTouchEvent方法,當onTouchEvent方法返回true,則事件處理到此結束,上面的父控件就不會再調用onTouchEvent方法。

4.如果某一個控件響應了ACTION_DOWN事件,則後續的ACTION_MOVE、ACTION_UP事件就會直接交給該控件處理,除非它的父控件攔截了後續的事件,但可以在處理ACTION_DOWN事件時,調用requestDisallowInterceptTouchEvent禁止父控件的攔截。如果控件沒有處理ACTION_DOWN事件,則後續的事件就不會再傳到該控件中,當下一次的ACTION_DOWN事件產生時,還是會傳給該View的。


四、下面來做一個演示

定義MainActivity、ParentView、ChildView,OnTouchListener

MainActivity——>媽媽

ParentView——>爸爸

ChildView——>我

OnTouchListener——>老婆

Event——>蘋果(一次來三個蘋果,模擬ACITON_DWON、ACTION_MOVE、ACTION_UP事件)

用一家人吃蘋果這個案例,模擬觸摸事件的處理。


媽媽MainActivity源碼:

package com.test.activity;

import com.example.javawebtest.R;

import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.app.Activity;

public class MainActivity extends Activity {

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
    	// TODO Auto-generated method stub
    	boolean eat = false;
    	Log.i(getClass().getSimpleName(), "媽媽" + (eat ? "吃了蘋果" : "沒有吃,扔了"));
    	return eat;
    }
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    	// TODO Auto-generated method stub
    	Log.i(getClass().getSimpleName(), "媽媽想分給爸爸蘋果");
    	return super.dispatchTouchEvent(ev);
    }

}


爸爸ParentView的源碼:

package com.test.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class ParentView extends RelativeLayout {

	public ParentView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		Log.i(getClass().getSimpleName(), "爸爸想分給我蘋果");
		return super.dispatchTouchEvent(ev);
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		boolean intercept = false;
		Log.i(getClass().getSimpleName(), "爸爸" + (intercept ? "想吃" : "不想吃") + "蘋果");
		return intercept ? true : super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		boolean eat = false;
		Log.i(getClass().getSimpleName(), "爸爸" + (eat ? "吃了蘋果" : "沒有吃,給了媽媽"));
		return eat;
	}

}

我ChildView、老婆OnTouchListener的源碼:

package com.test.view;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class ChildView extends View implements OnTouchListener {

	public ChildView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		setOnTouchListener(this);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		boolean eat = false;
		Log.i(getClass().getSimpleName(), "我" + (eat ? "吃了蘋果" : "沒有吃蘋果,給了爸爸"));
		return eat;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		boolean eat = false;
		Log.i(getClass().getSimpleName(), "老婆" + (eat ? "吃了蘋果" : "沒有吃蘋果,給了我"));
		return eat;
	}
	
}


場景一:大家誰也沒吃蘋果,效果如下圖

\

剛開始,第一個蘋果一直往下傳,誰也沒吃,後面媽媽知道我們都不喜歡吃蘋果,第二、第三個蘋果都沒有傳給我們,就扔了...


<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+IAogs6G+sLb+o7rO0rPUwcvGu7n7o6y9q0NoaWxkVmlld7XEb25Ub3VjaEV2ZW50tcRlYXTWw86qdHJ1ZTwvcD4KPHA+PGltZyBzcmM9"/uploadfile/Collfiles/20141221/2014122109040324.png" alt="\">

我吃了蘋果,不過每次吃之前都要詢問老婆,要是老婆吃了,我就不能吃...


場景三:爸爸搶了蘋果,將onInterceptTouchEvent的intercept置為true


結果蘋果被老爸吃了,然後再沒有我的事情了...

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved