中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

老生常談android中的事件傳遞和處理機制

發布時間:2020-09-11 18:24:36 來源:腳本之家 閱讀:130 作者:jingxian 欄目:移動開發

一直以來,都被android中的事件傳遞和處理機制深深的困擾!今天特意來好好的探討一下。現在的感覺是,只要你理解到位,其實事件的

傳遞和處理機制并沒有想象中的那么難。總之,不要自己打擊自己,要相信自己能掌握這塊知識。好了,下面是我今天的收獲,希望也

能對你有一點幫助。

一、擬人化來理解android中的事件機制

其實android中的事件傳遞與處理機制跟我們生活中的事件處理是一樣的。這里有一個生活中的例子,很能說明這個問題。闡述如下:

你是一個公司的員工,你的上頭有一個主管,主管上頭呢還有一個經理。為了簡單,你們這個團隊就有這三個人。那么如果上頭安排一件事下來要處理,流程是怎樣的呢?顯然應該是由你的經理將這件事安排給你的主管來處理,你的主管再將這件事安排給你來處理。等你把這件事辦好了,你就應該給你的主管報告,再由你的主管來向你的經理報告。顯然,你的主管和經理也有處理這件事的權限,如果他們覺得事情很復雜,你辦不了,或者他們比較照顧下級,可能就自己把這件事給辦了,這個時候這件事就不會再傳遞給下一級來處理了。這個事件處理的過程,是不是太容易理解了!

其實android中的事件處理流程就是跟生活中的事件處理是一樣的。比如你在ViewGroupA中嵌套了一個VewiGroupB,然后又在ViewGroupB

中嵌套了一個MyView。那么一個觸摸事件傳遞過來,會發生什么情況呢?類比上面的公司員工的處理事件,顯然會發生下面的過程:

觸摸事件傳遞過來后,ViewGroupA一看自己里面還有一個員工可以利用,就是ViewGroupB,那不用白不用,就會把這個事件傳遞給ViewGroupB,告訴他,你給我把這個事件處理了!

ViewGroupB呢一看,我不怕,我里面也有一個員工就是MyView,它得給我干活,于是又會把這個事件傳遞給MyView,讓它來處理。MyView一看,沒辦法啊,我手底下沒有員工了,那怎么辦,我只能自己處理了(前提是它有處理這個事件的能力),所以就把這個觸摸事件給處理了。處理完成后呢?MyView就是給ViewGroupB報告,我已經把事情辦好了,你來審核一下
,看看辦理的咋樣。ViewGroupB一審核,覺得不錯,就再將結果呈現給ViewGroupA。ViewGroupA再審核,通過了才算通過。在這個過程中,也可能出現幾種情況:

(1)MyView說,完蛋了,這事我的能力辦不好啊,于是就向VeiwGroupB報告,我沒有處理,請你來處理,你是我上司,能力比我強。于是ViewGroupB就會來幫忙處理。當然了,

如果ViewGroupB也沒能力處理,那就只能反饋給VeiwGroupA,讓它來消化這個事件。

(2)也可能MyView處理非常完美,向ViewGroupB一報告,ViewGroupB一開心就說不用再交給ViewGroupA審核了,我擔保通過,于是事件到此直接終止。

上面用很形象的話來講adnroid中的事件傳遞和處理機制講解了一下。android用下面的幾個方法將上面的過程完美封裝了:

在ViewGroup中,有下面三個方法:
(1)dispatchTouchEvent   該方法用來分發事件,一般不會重寫這個方法
(2)onInterceptTouchEvent 用來攔截事件
(3)onTouchEvent      用來處理事件,這個方法應該大家很常見了吧

而View中,只有兩個方法,即:(1)dispatchTouchEvent   該方法用來分發事件,一般不會重寫這個方法
(2)onTouchEvent      用來處理事件,這個方法應該大家很常見了吧

那么我們就來寫一個實際的代碼,來驗證一下這些方法都對應上面的哪些過程。這樣子就會對這個些方法有更透徹的理解。

二、根據實戰代碼來分析各個方法

下面我們就來把上面提到的ViewGroupA,ViewGroupB,還有MyView給編寫出來。

新建一個項目,先來寫ViewGruopA,代碼如下:

package com.example.testmotionevent;

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

public class ViewGroupA extends LinearLayout{

  public ViewGroupA(Context context) {
    super(context);
  }
  public ViewGroupA(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  public ViewGroupA(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
  
  
  

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    
    Log.d("付勇焜----->","ViewGroupA dispatchTouchEvent");
    return super.dispatchTouchEvent(ev);
  }
  
  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    
    Log.d("付勇焜----->","ViewGroupA onInterceptTouchEvent");
    return super.onInterceptTouchEvent(ev);
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    Log.d("付勇焜----->","ViewGroupA onTouchEvent");
    return super.onTouchEvent(event);
  }
}

代碼很簡單,就不用我解釋了吧,無非就是重寫上面提到的那幾個方法,然后打印相關的標記,來觀察事件的處理機制。

同理,編寫ViewGroupB,如下:

package com.example.testmotionevent;

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

public class ViewGroupB extends LinearLayout{

  public ViewGroupB(Context context) {
    super(context);
  }
  public ViewGroupB(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  public ViewGroupB(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
  
  
  

  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
    
    Log.d("付勇焜----->","ViewGroupB dispatchTouchEvent");
    return super.dispatchTouchEvent(ev);
  }
  
  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    
    Log.d("付勇焜----->","ViewGroupB onInterceptTouchEvent");
    return super.onInterceptTouchEvent(ev);
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    Log.d("付勇焜----->","ViewGroupB onTouchEvent");
    return super.onTouchEvent(event);
  }
}

然后再編寫MyView,如下:

package com.example.testmotionevent;

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

public class MyView extends View{

  public MyView(Context context) {
    super(context);
  }
  public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }
  public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
  
  
  @Override
  public boolean dispatchTouchEvent(MotionEvent event) {
    Log.d("付勇焜---->","MyView dispatchTouchEvent ");
    return super.dispatchTouchEvent(event);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    
    Log.d("付勇焜---->","MyView onTouchEvent ");
    return super.onTouchEvent(event);
  }
}

好了,現在就將它們嵌套在一起,修改activity_main.xml,如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  >

  <com.example.testmotionevent.ViewGroupA
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:background="#ff0033">
    <com.example.testmotionevent.ViewGroupB
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:gravity="center"
    android:background="#336699">
     <com.example.testmotionevent.MyView
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:clickable="true"
    android:background="#ffff00"/>
    
      
    </com.example.testmotionevent.ViewGroupB>
    
    
  </com.example.testmotionevent.ViewGroupA>
    

</LinearLayout>

嵌套完成,運行程序,是什么樣子的呢?如下圖:

老生常談android中的事件傳遞和處理機制

紅色的就是ViewGroupA,藍色的就是ViewGroupB,黃色就是MyView。現在來點擊中間黃色的MyView,觀察下打印結果,如下:

老生常談android中的事件傳遞和處理機制

從打印的結果,我們可以很清楚到看到事件的流程:

首先ViewGroupA得到了事件,由它的dispatchTouchEvent方法來分發事件,由于它的onInterceptTouchEvent方法沒有做出攔截,因此事件傳遞給了ViewGroupB,

而同樣由于ViewGroupB的onInterceptTouchEvent方法在它的dispatchTouchEvent方法分發事件時沒有做出攔截,故而事件最終被傳遞給MyView,MyView就來處理這個事件了。

下面我們來做實驗吧,我們讓MyView沒有處理這個事件,會是上面我們所說的由ViewGrouPB來處理嗎?修改MyView的onTouchEvent事件,如下:

 public boolean onTouchEvent(MotionEvent event) {
    
    Log.d("付勇焜---->","MyView onTouchEvent ");
    return false;
//    return super.onTouchEvent(event);
  }

我們return了false,表示MyView沒有成功處理這個事件。現在來再運行下程序,打印結果如下:

老生常談android中的事件傳遞和處理機制

由于MyView的onTouchEvent返回false,因此事件就交給了它的上級ViewGroupB來處理,于是ViewGroupB的onTouchEvent就來消化這個事件了。所以

從打印的結果來看正是這個情況(即紅色線條標注的部分)。但是由于ViewGroupB的onTouchEvent也沒有成功處理這個事件所以又傳遞給ViewGroupA的

onToucEvent來處理這個事件(即紅色線最下面還有ViewGroupA的標志)。不管ViewGroupA能不能成功處理,我們的程序中它是終極boss,不會再由其他對象

來處理該事件了。

再來在上一步的基礎上繼續做實驗。當MyView沒有成功處理事件,傳遞給ViewGroupB來處理時,當ViewGroupB處理完,我們強制告知程序,ViewGroupB

已經成功處理該事件了,看看會出現什么情況!修改ViewGroupB的onTouchEvent代碼,如下:

public boolean onTouchEvent(MotionEvent event) {
    Log.d("付勇焜----->","ViewGroupB onTouchEvent");
    
    return true; //表示事件已經成功處理
//    return super.onTouchEvent(event);
  }

再來運行程序,觀察打印結果如下:

老生常談android中的事件傳遞和處理機制

觀察紅線部分,此時只剩下ViewGroupB的onTouchEvent了。因為ViewGroupB已經成功處理這事件了,那就不必再勞煩ViewGroupA來吃處理了。

好了,現在我們在上一個實驗的基礎上再來實驗。比如,當事件傳遞到ViewGroupB的時候,ViewGroupB比較好心,心想干脆我來處理這個事情吧,就不必再讓MyView

加班了,于是他對這個事件進行了攔截!修改ViewGroupB的onInterceptTouchEvent代碼,如下:

@Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    
    Log.d("付勇焜----->","ViewGroupB onInterceptTouchEvent");
    return true;
//    return super.onInterceptTouchEvent(ev);
  }

再次運行程序,觀察打印結果,如下:

老生常談android中的事件傳遞和處理機制

我們發現事件傳遞到ViewGroupB的地方直接終止了,然后就是ViewGroupB的onTouchEvent事件來處理了,當然了因為之前我們強制修改ViewGroupB的onTouchEvent

為處理成功,因此也不會再返回給ViewGroupA的onTouchEvent來處理了。此時MyView壓根就不知道有個觸摸事件在它的上層傳遞呢!所以在打印結果中,我們連MyView的影子

都見不到!

好了,我就帶大家做這幾個實驗吧。已經足夠說明問題了。下面我們就來做一下總概述吧。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

從上面的實驗我們可以很清晰的看到一個事件處理的流程,在正常情況下,是如下圖的這樣子的一個流程

老生常談android中的事件傳遞和處理機制

也就是說,一個事件是必須要先經過傳遞流程才會再經過處理流程。這個先后順序一定要明白。如果你無法理解,請再想一想上面擬人化的公司員工處理事件的流程吧。

其中,在紅色線和藍色線代表傳遞的流程中,我們都可以進行所謂的攔截事件。說明如下:

對于事件的攔截,我們主要重寫就是OnInterceptTouchEvent和onTouchEvent方法。

兩句就可以總結:

(1)對于事件的傳遞,返回結果為true,表示攔截,不再往下傳遞,為false,不攔截,繼續往下傳遞。主要針對的就是OnInterceptTouchEvent方法。

(2)對于事件的處理,返回結果為true,表示攔截,不再往上傳遞(即我處理的很完美,不需要你再來審核我!),返回結果為false(沒有成功處理事件),繼續向上傳遞。 針對就是onTouchEvent方法。

因此我們就可以通過控制OnInterceptTouchEvent和onTouchEvent方法的返回值來控制整個事件的傳遞流程和處理流程!!到此,你是不是對andorid中的事件的整個處理機制很

明白了呢?以后再出現什么問題,是不是就可以順藤摸瓜,找到問題所在了!

三、總結

如果你嫌上面的解釋太啰嗦了。那么就只看下面的這個總結就可以了,一下就找到關鍵的知識點!如下:

(1)正常情況下,android中的事件是必須要經過傳遞流程然后再經過處理流程的。要記住這個先后的順序。

(2)在傳遞流程和處理流程中,你都可以修改方法的返回值,來對流程做控制。

如下:

對于事件的攔截,我們主要重寫就是OnInterceptTouchEvent和onTouchEvent方法。兩句就可以總結:

事件的傳遞,返回結果為true,表示攔截,不再往下傳遞,為false,不攔截,繼續往下傳遞。主要針對的就是OnInterceptTouchEvent方法。

事件的處理,返回結果為true,表示攔截,不再往上傳遞(即我處理的很完美,不需要你再來審核我!),返回結果為false(沒有成功處理事件),繼續向上傳遞。

針對就是onTouchEvent方法。

(3)如果流程你還理解,就好好想一想那個公司員工的擬人化解釋吧!實際上android的事件處理機制原理就是這樣子的!

以上這篇老生常談android中的事件傳遞和處理機制就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

丰顺县| 沙坪坝区| 界首市| 万州区| 威海市| 上虞市| 斗六市| 永川市| 遵化市| 泌阳县| 时尚| 祁门县| 台北县| 蒙山县| 丰宁| 崇礼县| 如皋市| 封丘县| 贺州市| 北海市| 宁南县| 独山县| 佛山市| 肇庆市| 明光市| 侯马市| 连山| 忻城县| 桐乡市| 澎湖县| 仁化县| 长乐市| 静宁县| 岳西县| 湘西| 金门县| 安乡县| 体育| 铜鼓县| 宾阳县| 达日县|