亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android事件傳遞機制

 更新時間:2016年02月03日 10:45:35   作者:Windstep  
這篇文章主要介紹了Android事件傳遞機制的相關資料,需要的朋友可以參考下

實驗環(huán)境

OS X 10.9
Eclipse(ADT)
Android源碼版本:API Level 19(Android 4.4)

Android事件構成

在Android中,事件主要包括點按、長按、拖拽、滑動等,點按又包括單擊和雙擊,另外還包括單指操作和多指操作。所有這些都構成了Android中的事件響應??偟膩碚f,所有的事件都由如下三個部分作為基礎:

按下(ACTION_DOWN)
移動(ACTION_MOVE)
抬起(ACTION_UP)

所有的操作事件首先必須執(zhí)行的是按下操作(ACTIONDOWN),之后所有的操作都是以按下操作作為前提,當按下操作完成后,接下來可能是一段移動(ACTIONMOVE)然后抬起(ACTION_UP),或者是按下操作執(zhí)行完成后沒有移動就直接抬起。這一系列的動作在Android中都可以進行控制。

我們知道,所有的事件操作都發(fā)生在觸摸屏上,而在屏幕上與我們交互的就是各種各樣的視圖組件(View),在Android中,所有的視圖都繼承于View,另外通過各種布局組件(ViewGroup)來對View進行布局,ViewGroup也繼承于View。所有的UI控件例如Button、TextView都是繼承于View,而所有的布局控件例如RelativeLayout、容器控件例如ListView都是繼承于ViewGroup。所以,我們的事件操作主要就是發(fā)生在View和ViewGroup之間,那么View和ViewGroup中主要有哪些方法來對這些事件進行響應呢?記住如下3個方法,我們通過查看View和ViewGroup的源碼可以看到:

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)

在View和ViewGroup中都存在dispatchTouchEvent和onTouchEvent方法,但是在ViewGroup中還有一個onInterceptTouchEvent方法,那這些方法都是干嘛的呢?別急,我們先看看他們的返回值。這些方法的返回值全部都是boolean型,為什么是boolean型呢,看看本文的標題,“事件傳遞”,傳遞的過程就是一個接一個,那到了某一個點后是否要繼續(xù)往下傳遞呢?你發(fā)現(xiàn)了嗎,“是否”二字就決定了這些方法應該用boolean來作為返回值。沒錯,這些方法都返回true或者是false。在Android中,所有的事件都是從開始經(jīng)過傳遞到完成事件的消費,這些方法的返回值就決定了某一事件是否是繼續(xù)往下傳,還是被攔截了,或是被消費了。

接下來就是這些方法的參數(shù),都接受了一個MotionEvent類型的參數(shù),MotionEvent繼承于InputEvent,用于標記各種動作事件。之前提到的ACTIONDOWN、ACTIONMOVE、ACTION_UP都是MotinEvent中定義的常量。我們通過MotionEvent傳進來的事件類型來判斷接收的是哪一種類型的事件。到現(xiàn)在,這三個方法的返回值和參數(shù)你應該都明白了,接下來就解釋一下這三個方法分別在什么時候處理事件。

dispatchTouchEvent方法用于事件的分發(fā),Android中所有的事件都必須經(jīng)過這個方法的分發(fā),然后決定是自身消費當前事件還是繼續(xù)往下分發(fā)給子控件處理。返回true表示不繼續(xù)分發(fā),事件沒有被消費。返回false則繼續(xù)往下分發(fā),如果是ViewGroup則分發(fā)給onInterceptTouchEvent進行判斷是否攔截該事件。

onTouchEvent方法用于事件的處理,返回true表示消費處理當前事件,返回false則不處理,交給子控件進行繼續(xù)分發(fā)。
onInterceptTouchEvent是ViewGroup中才有的方法,View中沒有,它的作用是負責事件的攔截,返回true的時候表示攔截當前事件,不繼續(xù)往下分發(fā),交給自身的onTouchEvent進行處理。返回false則不攔截,繼續(xù)往下傳。這是ViewGroup特有的方法,因為ViewGroup中可能還有子View,而在Android中View中是不能再包含子View的(iOS可以)。
到目前為止,Android中事件的構成以及事件處理方法的作用你應該比較清楚了,接下來我們就通過一個Demo來實際體驗實驗一下。

Android事件處理

首先在Eclipse新建一個工程,并新建一個類RTButton繼承Button,用來實現(xiàn)我們對按鈕事件的跟蹤。

RTButton.java

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);
}
}

在RTButton中我重寫了dispatchTouchEvent和onTouchEvent方法,并獲取了MotionEvent各個事件狀態(tài),打印輸出了每一個狀態(tài)下的信息。然后在activity_main.xml中直接在根布局下放入自定義的按鈕RTButton。

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/myLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.ryantang.eventdispatchdemo.RTButton 
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button"/>
</LinearLayout>

接下來在Activity中為RTButton設置onTouch和onClick的監(jiān)聽器來跟蹤事件傳遞的過程,另外,Activity中也有一個dispatchTouchEvent方法和一個onTouchEvent方法,我們也重寫他們并輸出打印信息。

MainActivity.java

public class MainActivity extends Activity {
private RTButton button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (RTButton)this.findViewById(R.id.btn);
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!");
}
});
}
@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);
}
}

代碼部分已經(jīng)完成了,接下來運行工程,并點擊按鈕,查看日志輸出信息,我們可以看到如下結(jié)果:

 

通過日志輸出可以看到,首先執(zhí)行了Activity的dispatchTouchEvent方法進行事件分發(fā),在MainActivity.java代碼第55行,dispatchTouchEvent方法的返回值是super.dispatchTouchEvent(event),因此調(diào)用了父類方法,我們進入Activity.java的源碼中看看具體實現(xiàn)。

Activity.java

/**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
* 
* @param ev The touch screen event.
* 
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}

從源碼中可以看到,dispatchTouchEvent方法只處理了ACTIONDOWN事件,前面提到過,所有的事件都是以按下為起點的,所以,Android認為當ACTIONDOWN事件沒有執(zhí)行時,后面的事件都是沒有意義的,所以這里首先判斷ACTION_DOWN事件。如果事件成立,則調(diào)用了onUserInteraction方法,該方法可以在Activity中被重寫,在事件被分發(fā)前會調(diào)用該方法。該方法的返回值是void型,不會對事件傳遞結(jié)果造成影響,接著會判斷getWindow().superDispatchTouchEvent(ev)的執(zhí)行結(jié)果,看看它的源碼:

Activity.java

/**
* Used by custom windows, such as Dialog, to pass the touch screen event
* further down the view hierarchy. Application developers should
* not need to implement or call this.
*
*/
public abstract boolean superDispatchTouchEvent(MotionEvent event);

通過源碼注釋我們可以了解到這是個抽象方法,用于自定義的Window,例如自定義Dialog傳遞觸屏事件,并且提到開發(fā)者不需要去實現(xiàn)或調(diào)用該方法,系統(tǒng)會完成,如果我們在MainActivity中將dispatchTouchEvent方法的返回值設為true,那么這里的執(zhí)行結(jié)果就為true,從而不會返回執(zhí)行onTouchEvent(ev),如果這里返回false,那么最終會返回執(zhí)行onTouchEvent方法,由此可知,接下來要調(diào)用的就是onTouchEvent方法了。別急,通過日志輸出信息可以看到,ACTION_DOWN事件從Activity被分發(fā)到了RTButton,接著執(zhí)行了onTouch和onTouchEvent方法,為什么先執(zhí)行onTouch方法呢?我們到RTButton中的dispatchTouchEvent看看View中的源碼是如何處理的。

View.java

/**
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(event, 0);
}
if (onFilterTouchEventForSecurity(event)) {
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null && (mViewFlags &
ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) {
return true;
}
if (onTouchEvent(event)) {
return true;
}
}
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
}
return false;
}

挑選關鍵代碼進行分析,可以看代碼第16行,這里有幾個條件,當幾個條件都滿足時該方法就返回true,當條件li.mOnTouchListener不為空時,通過在源碼中查找,發(fā)現(xiàn)mOnTouchListener是在以下方法中進行設置的。

View.java

/**
* Register a callback to be invoked when a touch event is sent to this view.
* @param l the touch listener to attach to this view
*/
public void setOnTouchListener(OnTouchListener l) {
getListenerInfo().mOnTouchListener = l;
}

這個方法就已經(jīng)很熟悉了,就是我們在MainActivity.java中為RTButton設置的onTouchListener,條件(mViewFlags & ENABLED_MASK) == ENABLED判斷的是當前View是否是ENABLE的,默認都是ENABLE狀態(tài)的。接著就是li.mOnTouchListener.onTouch(this, event)條件,這里調(diào)用了onTouch方法,該方法的調(diào)用就是我們在MainActivity.java中為RTButton設置的監(jiān)聽回調(diào),如果該方法返回true,則整個條件都滿足,dispatchTouchEvent就返回true,表示該事件就不繼續(xù)向下分發(fā)了,因為已經(jīng)被onTouch消費了。

如果onTouch返回的是false,則這個判斷條件不成立,接著執(zhí)行onTouchEvent(event)方法進行判斷,如果該方法返回true,表示事件被onTouchEvent處理了,則整個dispatchTouchEvent就返回true。到這里,我們就可以回答之前提出的“為什么先執(zhí)行onTouch方法”的問題了。到目前為止,ACTIONDOWN的事件經(jīng)過了從Activity到RTButton的分發(fā),然后經(jīng)過onTouch和onTouchEvent的處理,最終,ACTIONDOWN事件交給了RTButton得onTouchEvent進行處理。

當我們的手(我這里用的Genymotion然后用鼠標進行的操作,用手的話可能會執(zhí)行一些ACTIONMOVE操作)從屏幕抬起時,會發(fā)生ACTIONUP事件。從之前輸出的日志信心中可以看到,ACTIONUP事件同樣從Activity開始到RTButton進行分發(fā)和處理,最后,由于我們注冊了onClick事件,當onTouchEvent執(zhí)行完畢后,就調(diào)用了onClick事件,那么onClick是在哪里被調(diào)用的呢?繼續(xù)回到View.java的源代碼中尋找。由于onTouchEvent在View.java中的源碼比較長,這里就不貼出來了,感興趣的可以自己去研究一下,通過源碼閱讀,我們在ACTIONUP的處理分支中可以看到一個performClick()方法,從這個方法的源碼中可以看到執(zhí)行了哪些操作。

View.java

/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
* a sound, etc.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
public boolean performClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
return true;
}
return false;
}

在if分支里可以看到執(zhí)行了li.mOnClickListener.onClick(this);這句代碼,這里就執(zhí)行了我們?yōu)镽TButton實現(xiàn)的onClick方法,所以,到目前為止,可以回答前一個“onClick是在哪里被調(diào)用的呢?”的問題了,onClick是在onTouchEvent中被執(zhí)行的,并且,onClick要后于onTouch的執(zhí)行。

到此,點擊按鈕的事件傳遞就結(jié)束了,我們結(jié)合源代碼窺探了其中的執(zhí)行細節(jié),如果我們修改各個事件控制方法的返回值又會發(fā)生什么情況呢,帶著這個問題,進入下一節(jié)的討論。

Android事件攔截

從上一節(jié)分析中,我們知道了在Android中存在哪些事件類型,事件的傳遞過程以及在源碼中對應哪些處理方法。我們可以知道在Android中,事件是通過層級傳遞的,一次事件傳遞對應一個完整的層級關系,例如上節(jié)中分析的ACTIONDOWN事件從Activity傳遞到RTButton,ACTIONUP事件也同樣。結(jié)合源碼分析各個事件處理的方法,也可以明確看到事件的處理流程。

之前提過,所有事件處理方法的返回值都是boolean類型的,現(xiàn)在我們來修改這個返回值,首先從Activity開始,根據(jù)之前的日志輸出結(jié)果,首先執(zhí)行的是Activity的dispatchTouchEvent方法,現(xiàn)在將之前的返回值super.dispatchTouchEvent(event)修改為true,然后重新編譯運行并點擊按鈕,看到如下的日志輸出結(jié)果。

可以看到,事件執(zhí)行到dispatchTouchEvent方法就沒有再繼續(xù)往下分發(fā)了,這也驗證了之前的說法,返回true時,不再繼續(xù)往下分發(fā),從之前分析過的Activity的dispatchTouchEvent源碼中也可知,當返回true時,就沒有去執(zhí)行onTouchEvent方法了。

接著,將上述修改還原,讓事件在Activity這繼續(xù)往下分發(fā),接著就分發(fā)到了RTButton,將RTButton的dispatchTouchEvent方法的返回值修改為true,重新編譯運行并查看輸出日志結(jié)果。

從結(jié)果可以看到,事件在RTButton的dispatchTouchEvent方法中就沒有再繼續(xù)往下分發(fā)了。接著將上述修改還原,將RTButton的onTouchEvent方法返回值修改為true,讓其消費事件,根據(jù)之前的分析,onClick方法是在onTouchEvent方法中被調(diào)用的,事件在這被消費后將不會調(diào)用onClick方法了,編譯運行,得到如下日志輸出結(jié)果。

跟分析結(jié)果一樣,onClick方法并沒有被執(zhí)行,因為事件在RTButton的onTouchEvent方法中被消費了。下圖是整個事件傳遞的流程圖。

到目前為止,Android中的事件攔截機制就分析完了。但這里我們只討論了單布局結(jié)構下單控件的情況,如果是嵌套布局,那情況又是怎樣的呢?接下來我們就在嵌套布局的情況下對Android的事件傳遞機制進行進一步的探究和分析。

Android嵌套布局事件傳遞

首先,新建一個類RTLayout繼承于LinearLayout,同樣重寫dispatchTouchEvent和onTouchEvent方法,另外,還需要重寫onInterceptTouchEvent方法,在文章開頭介紹過,這個方法只有在ViewGroup和其子類中才存在,作用是控制是否需要攔截事件。這里不要和dispatchTouchEvent弄混淆了,后者是控制對事件的分發(fā),并且后者要先執(zhí)行。

那么,事件是先傳遞到View呢,還是先傳遞到ViewGroup的?通過下面的分析我們可以得出結(jié)論。首先,我們需要對工程代碼進行一些修改。

RTLayout.java

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);
}
}

同時,在布局文件中為RTButton添加一個父布局,指明為自定義的RTLayout,修改后的布局文件如下。

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.ryantang.eventdispatchdemo.RTLayout
android:id="@+id/myLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.ryantang.eventdispatchdemo.RTButton
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
</com.ryantang.eventdispatchdemo.RTLayout>
</LinearLayout>

最后,我們在Activity中也為RTLayout設置onTouch和onClick事件,在MainActivity中添加如下代碼。

MainActivity.java

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 false;
}
});
rtLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("RTLayout clicked!");
}
});

代碼修改完畢后,編譯運行工程,同樣,點擊按鈕,查看日志輸出結(jié)果如下:

從日志輸出結(jié)果我們可以看到,嵌套了RTLayout以后,事件傳遞的順序變成了Activity->RTLayout->RTButton,這也就回答了前面提出的問題,Android中事件傳遞是從ViewGroup傳遞到View的,而不是反過來傳遞的。

從輸出結(jié)果第三行可以看到,執(zhí)行了RTLayout的onInterceptTouchEvent方法,該方法的作用就是判斷是否需要攔截事件,我們到ViewGroup的源碼中看看該方法的實現(xiàn)。

ViewGroup.java

public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}

該方法的實現(xiàn)很簡單,只返回了一個false。那么這個方法是在哪被調(diào)用的呢,通過日志輸出分析可知它是在RTLayout的dispatchTouchEvent執(zhí)行后執(zhí)行的,那我們就進到dispatchTouchEvent源碼里面去看看。由于源碼比較長,我將其中的關鍵部分截取出來做解釋說明。

ViewGroup.java

// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}

從這部分代碼中可以看到onInterceptTouchEvent調(diào)用后返回值被賦值給intercepted,該變量控制了事件是否要向其子控件分發(fā),所以它起到攔截的作用,如果onInterceptTouchEvent返回false則不攔截,如果返回true則攔截當前事件。我們現(xiàn)在將RTLayout中的該方法返回值修改為true,并重新編譯運行,然后點擊按鈕,查看輸出結(jié)果如下。

可以看到,我們明明點擊的按鈕,但輸出結(jié)果顯示RTLayout點擊事件被執(zhí)行了,再通過輸出結(jié)果分析,對比上次的輸出結(jié)果,發(fā)現(xiàn)本次的輸出結(jié)果完全沒有RTButton的信息,沒錯,由于onInterceptTouchEvent方法我們返回了true,在這里就將事件攔截了,所以他不會繼續(xù)分發(fā)給RTButton了,反而交給自身的onTouchEvent方法執(zhí)行了,理所當然,最后執(zhí)行的就是RTLayout的點擊事件了。

總結(jié)

以上我們對Android事件傳遞機制進行了分析,期間結(jié)合系統(tǒng)源碼對事件傳遞過程中的處理情況進行了探究。通過單布局情況和嵌套布局情況下的事件傳遞和處理進行了分析,現(xiàn)總結(jié)如下:

Android中事件傳遞按照從上到下進行層級傳遞,事件處理從Activity開始到ViewGroup再到View。
事件傳遞方法包括dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent,其中前兩個是View和ViewGroup都有的,最后一個是只有ViewGroup才有的方法。這三個方法的作用分別是負責事件分發(fā)、事件處理、事件攔截。
onTouch事件要先于onClick事件執(zhí)行,onTouch在事件分發(fā)方法dispatchTouchEvent中調(diào)用,而onClick在事件處理方法onTouchEvent中被調(diào)用,onTouchEvent要后于dispatchTouchEvent方法的調(diào)用。

相關文章

  • Android開發(fā)中的簡單設置技巧集錦

    Android開發(fā)中的簡單設置技巧集錦

    這篇文章主要介紹了Android開發(fā)中的簡單設置技巧,較為詳細的匯總了Android針對壁紙、語言、音量、錄音等多種設置的方法,非常簡單實用,需要的朋友可以參考下
    2016-06-06
  • 詳解Android中Dialog的使用

    詳解Android中Dialog的使用

    在Android中經(jīng)常要使用Dialog來實現(xiàn)一些提示以及一些特殊的效果,這里總結(jié)一些常用的Dialog的實踐,非常具有實用價值,需要的朋友可以參考下。
    2017-01-01
  • 微信小程序—微信跳一跳,Android游戲助手(外掛)使用教程詳解

    微信小程序—微信跳一跳,Android游戲助手(外掛)使用教程詳解

    這篇文章主要介紹了微信小程序—微信跳一跳,Android游戲助手(外掛)使用教程詳解,需要的朋友可以參考下
    2018-01-01
  • Android動畫之漸變動畫(Tween Animation)詳解 (漸變、縮放、位移、旋轉(zhuǎn))

    Android動畫之漸變動畫(Tween Animation)詳解 (漸變、縮放、位移、旋轉(zhuǎn))

    這篇文章主要介紹了Android動畫之漸變動畫(Tween Animation)用法,結(jié)合實例形式詳細分析了Android漸變動畫Tween Animation實現(xiàn)漸變,縮放,位移,旋轉(zhuǎn)等技巧,需要的朋友可以參考下
    2016-01-01
  • Android評分RationBar控件使用詳解

    Android評分RationBar控件使用詳解

    這篇文章主要為大家詳細介紹了Android評分RationBar控件的使用方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Android實現(xiàn)藍牙聊天功能

    Android實現(xiàn)藍牙聊天功能

    這篇文章主要為大家詳細介紹了Android實現(xiàn)藍牙聊天功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Android實現(xiàn)三段式滑動效果

    Android實現(xiàn)三段式滑動效果

    最近發(fā)現(xiàn)很多app都使用了三段式滑動,比如說高德的首頁和某寶等物流信息都是使用的三段式滑動方式,谷歌其實給了我們很好的2段式滑動,就是BottomSheet,所以這次我也是在這個原理基礎上做了一個小小的修改來實現(xiàn)我們今天想要的效果。
    2021-06-06
  • Android View 事件分發(fā)機制詳解

    Android View 事件分發(fā)機制詳解

    本文主要介紹Android View 事件分發(fā)機制,這里整理了相關資料并詳細介紹了view分發(fā)機制的知識及簡單示例代碼,有興趣的小伙伴可以參考下
    2016-08-08
  • Android開發(fā)從相機或相冊獲取圖片裁剪

    Android開發(fā)從相機或相冊獲取圖片裁剪

    當我們需要上傳圖片時,想要裁剪成我們需要的尺寸大小,android手機都帶有這個功能,很容易,那么此功能是如何實現(xiàn)的呢?下面小編給大家介紹Android開發(fā)從相機或相冊獲取圖片裁剪,需要的朋友可以參考下
    2015-10-10
  • Android 重力傳感器在游戲開發(fā)中的應用

    Android 重力傳感器在游戲開發(fā)中的應用

    本文主要介紹Android 重力傳感器,這里整理了詳細的資料,并且詳細的說明重力傳感器的使用方法,有興趣的小伙伴可以參考下
    2016-08-08

最新評論