編輯:關於Android編程
今天給大家代碼ViewGroup事件分發的源碼解析~~凡是自定義ViewGroup實現各種滑動效果的,不可避免的會出現很多事件的沖突,對ViewGroup事件分發機制的了解,也有益於大家了解沖突產生的原因,以及對沖突進行處理~
首先我們接著上一篇的代碼,在代碼中添加一個自定義的LinearLayout:
package com.example.zhy_event03;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyLinearLayout extends LinearLayout
{
private static final String TAG = MyLinearLayout.class.getSimpleName();
public MyLinearLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev)
{
int action = ev.getAction();
switch (action)
{
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(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action = event.getAction();
switch (action)
{
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 onInterceptTouchEvent(MotionEvent ev)
{
int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "onInterceptTouchEvent ACTION_UP");
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept)
{
Log.e(TAG, "requestDisallowInterceptTouchEvent ");
super.requestDisallowInterceptTouchEvent(disallowIntercept);
}
}
繼承LinearLayout,然後復寫了與事件分發機制有關的代碼,添加上了日志的打印~
然後看我們的布局文件:
<com.example.zhy_event03.MyLinearLayout 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"
tools:context=".MainActivity" >
<com.example.zhy_event03.MyButton
android:id="@+id/id_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click me" />
</com.example.zhy_event03.MyLinearLayout>
MyLinearLayout中包含一個MyButton,MyButton都上篇博客中已經出現過,這裡就不再貼代碼了,不清楚可以去查看~
然後MainActivity就是直接加載布局,沒有任何代碼~~~
直接運行我們的代碼,然後點擊我們的Button,依然是有意的MOVE一下,不然不會觸發MOVE事件,看一下日志的輸出:
09-06 09:57:27.287: E/MyLinearLayout(959): dispatchTouchEvent ACTION_DOWN 09-06 09:57:27.287: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_DOWN 09-06 09:57:27.287: E/MyButton(959): dispatchTouchEvent ACTION_DOWN 09-06 09:57:27.297: E/MyButton(959): onTouchEvent ACTION_DOWN 09-06 09:57:27.297: E/MyButton(959): onTouchEvent ACTION_MOVE 09-06 09:57:27.327: E/MyLinearLayout(959): dispatchTouchEvent ACTION_MOVE 09-06 09:57:27.327: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_MOVE 09-06 09:57:27.337: E/MyButton(959): dispatchTouchEvent ACTION_MOVE 09-06 09:57:27.337: E/MyButton(959): onTouchEvent ACTION_MOVE 09-06 09:57:27.457: E/MyLinearLayout(959): dispatchTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyButton(959): dispatchTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyButton(959): onTouchEvent ACTION_UP
可以看到大體的事件流程為:
MyLinearLayout的dispatchTouchEvent -> MyLinearLayout的onInterceptTouchEvent -> MyButton的dispatchTouchEvent ->Mybutton的onTouchEvent
可以看出,在View上觸發事件,最先捕獲到事件的為View所在的ViewGroup,然後才會到View自身~
下面我們按照日志的輸出,進入源碼~
ViewGroup - dispatchTouchEvent
首先是ViewGroup的dispatchTouchEvent方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!onFilterTouchEventForSecurity(ev)) {
return false;
}
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
final float scrolledXFloat = xf + mScrollX;
final float scrolledYFloat = yf + mScrollY;
final Rect frame = mTempRect;
boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (action == MotionEvent.ACTION_DOWN) {
if (mMotionTarget != null) {
// this is weird, we got a pen down, but we thought it was
// already down!
// XXX: We should probably send an ACTION_UP to the current
// target.
mMotionTarget = null;
}
// If we're disallowing intercept or if we're allowing and we didn't
// intercept
if (disallowIntercept || !onInterceptTouchEvent(ev)) {
// reset this event's action (just to protect ourselves)
ev.setAction(MotionEvent.ACTION_DOWN);
// We know we want to dispatch the event down, find a child
// who can handle it, start with the front-most child.
final int scrolledXInt = (int) scrolledXFloat;
final int scrolledYInt = (int) scrolledYFloat;
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
child.getHitRect(frame);
if (frame.contains(scrolledXInt, scrolledYInt)) {
// offset the event to the view's coordinate system
final float xc = scrolledXFloat - child.mLeft;
final float yc = scrolledYFloat - child.mTop;
ev.setLocation(xc, yc);
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
if (child.dispatchTouchEvent(ev)) {
// Event handled, we have a target now.
mMotionTarget = child;
return true;
}
// The event didn't get handled, try the next view.
// Don't reset the event's location, it's not
// necessary here.
}
}
}
}
} ....//other code omitted
代碼比較長,決定分段貼出,首先貼出的是ACTION_DOWN事件相關的代碼。
16行:進入ACTION_DOWN的處理
17-23行:將mMotionTarget置為null
26行:進行判斷:if(disallowIntercept || !onInterceptTouchEvent(ev))
Android樣式的開發:drawable匯總篇
Android有很多種drawable類型,除了前幾篇詳細講解的shape、selector、layer-list,還有上一篇提到的color、bitmap、
Android編程四大組件分別是什麼
Android開發四大組件分別是:活動(Activity):用於表現功能。服務(Service):後台運行服務,不提供界面呈現。廣播接收器(BroadcastReceiv
Android官方文檔之Introduction
寫在前面的話:接觸Android的時間也不短了,聽了視頻、看了書、敲了代碼,寫了博客,做了demo。。。但是想做出一款優秀的APP(哪怕是封裝一個不錯的功能)還有很長的路
Android網絡編程之UDP通信模型實例
什麼是Android UDP?UDP是User Datagram Protocol的簡稱,中文名是用戶數據包協議,是OSI參考模型中一種無連接的傳輸層協議,提供面向事務的