Android事件的構成:
在android中,事件主要包括點按,長按,拖拽,滑動等等,另外點按還包括點擊和雙擊。所有這些都構成了android中的事件響應。總的來說所有的事件都由以下三個部分組成:
按下(ACTION_DOWM)
移動(ACTION_MOVE)
抬起(ACTION_UP)
所有操作首先執行的是按下的操作,之后所有的操作都是以按下作為前提的,這一系列的操作的可以在android中控制。
我們知道所有的事件操作都發生在觸屏幕上,而在屏幕上與我們交互的就是各種各樣 的視圖組件(View),在android中,所有的視圖都繼承于view,另外通過各種布局組件(viewgroup)來對view進行布局,viewgroup也繼承與view,所有的UI控件:例如Button,Textview等等;所有的布局控件:例如Relativelayout,listview都是繼承viewgroup.所有事件的操作主要發生在view和viewgroup之間,下面主要講一下view和viewgroup都有哪些方法來對事件進行響應。
1)dispatchTouchEvent() 這個方法用于實踐的分發2)onInterceptTouchEvent() 進行判斷是否攔截事件3)onTouchEvent() 這個方法用于事件的處理
所有的方法都接受了一個參數MotionEvent類型的參數,MotionEvent用于標記各種事件動作事件,返回值是boolean, 事件傳遞時一個接著一個,所以只有”是否“傳遞來決定,所以用boolean。
下面通過實例來分析view和viewgroup的關系:
單布局事件傳遞機制(view):
1.首先建立一個類RTButton繼承Button;重寫它的dispatchTouchEvent,onTouchEvent方法。分別在DOWN,MOVE,UP時打印句子,方便運行時查看。如下代碼:
public class RTButton extends Button {public RTButton(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (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;}// 獲取了MotionEvent各個事件狀態return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (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);}
}
2.在布局文件中放入自定義的按鈕.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><com.example.demo.RTButton android:id="@+id/rtbtn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="button"/>
</LinearLayout>
3.在MainActivity中添加按鈕的點擊事件,再添加按鈕的觸摸事件。
public class MainActivity extends Activity {private RTButton rtbtn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);rtbtn = (RTButton) findViewById(R.id.rtbtn);rtbtn.setOnTouchListener(new OnTouchListener() {@Override// 對按鈕的觸摸的監聽public boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (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;}});// 對按鈕的onclick監聽rtbtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubSystem.out.println("RTButton clicked");}});}// Activity的dispatchTouchEvent的事件@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubswitch (ev.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(ev);}@Override// 對Activity的ontouchevent的方法事件public boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (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");breakdefault:break;}return super.onTouchEvent(event);}
}
4.然后再給Activity重寫它的dispatchTouchEvent和onTouchEvent方法,并且都打印句子,然后運行得出結果如下:
通過查看運行結果,我們發現首先執行了Activity的dispatchTouchEvent方法。
附加:1.Android事件的阻擋(不是攔截事件,是通過改變return和false來阻擋事件)
例如第一種:事件是通過層次傳遞的,之前提過所有的事件處理方法的返回值都是boolean類型的,現在修改這個返回值,將Activity的dispatchTouchEvent方法的返回值super.dispatchTouchEvent改為true,然后重新運行結果如下:
從代碼上我們得知事件傳到了Activity就沒有再繼續往下傳了。
例如第二種:將上述的修改還原,讓事件在Activity分發下去,分發到RTButton,將RTButton的dispatchTouchEvent方法的返回值修改為true,運行結果如下:我們發現事件傳到RTButton的分發事件就沒有再往下傳遞了。
Android嵌套布局事件傳遞(view和viewgroup)
首先新建一個類RTLayout繼承LinearLayout,同樣重寫dispatchTouchEvent和onTouchEvent方法,另外還要重寫onInterceptTouchEvent方法(LinearLayout繼承ViewGroup),代碼如下:
public class RTLayout extends LinearLayout {public RTLayout(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubswitch (ev.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(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubswitch (ev.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(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubswitch (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
;}
}
主要研究事件傳遞時先傳遞到view還是先傳遞到viewgroup。下面進行詳解:
在原有的RTButton布局上加上自定義的RTLayout布局,在MainActivity中,操作與RTButton一樣,并且再加給RTLayout設置Ontouch和Onclick事件。然后運行代碼結果如下:
通過上面的代碼,我們看出當我們把信息攔截之后,就到不了RTButton上了,所以直接走到了RTLayout的Ontouch方法,所以才顯示RTLayout clicked;
總結:
1 . Android中時間傳遞按照從上到下的層級傳遞,事件處理從Activity到viewgroup到view的。事件傳遞方法包括dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent.分別負責分發,攔截,處理.
2.Ontouch事件要先于On click事件執行。因為Ontouch在事件分發方法dispatchTouchEvent中調用,而on click在時間處理方法onTouchEvent中被調用,onTouchEvent事件要后于dispatchTouchEvent方法的調用。
我的公眾號如下:
總結
以上是生活随笔為你收集整理的Android事件传递(分发)机制的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。