編輯:關於Android編程
什麼是分發?分發就是將一些事務交給下屬來處理,事件的分發其實包含了:事件的攔截,事件的處理(這樣說可能不是太准確)
事件攔截機制中,ViewGroup有onInterceptTouchEvent(),
dispatchTouchEvent(),
onTouchEvent()三個方法,分別起到事件分發、事件攔截、事件處理的作用
而View中只有dispatchTouchEvent(),
onTouchEvent()方法。
假設有這樣一個Layout: ViewGroupA -> ViewGroupB -> View
當用戶點擊了這個布局的時候,
首先會從最外層ViewGroupA開始進行判斷,首先將事件分發給子View(dispatchTouchEvent()),即子View具有優先處理的權利
ViewGroupA代碼如下
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
/**
* Created by feathers on 16-11-13.
*/
public class MyViewGroupA extends LinearLayout {
private final String TAG = "MyViewGroupA";
public MyViewGroupA(Context context) {
super(context);
}
public MyViewGroupA(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroupA(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i(TAG, "dispatchTouchEvent()");
boolean b = super.dispatchTouchEvent(ev);
Log.i(TAG, "dispatchTouchEvent() return ");
return b;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG, "onInterceptTouchEvent()");
boolean b = super.onInterceptTouchEvent(ev);
Log.i(TAG, "onInterceptTouchEvent() return");
return b;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "onTouchEvent()");
boolean b = super.onTouchEvent(event);
Log.i(TAG, "onTouchEvent() return");
return b;
}
}
ViewGroupB代碼同A類似:
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
/**
* Created by feathers on 16-11-13.
*/
public class MyViewGroupB extends LinearLayout {
private final String TAG = "MyViewGroupB";
public MyViewGroupB(Context context) {
super(context);
}
public MyViewGroupB(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroupB(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i(TAG, "dispatchTouchEvent()");
boolean b = super.dispatchTouchEvent(ev);
Log.i(TAG, "dispatchTouchEvent() return");
return b;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG, "onInterceptTouchEvent()");
boolean b = super.onInterceptTouchEvent(ev);
Log.i(TAG, "onInterceptTouchEvent() return ");
return b;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "onTouchEvent()");
boolean b = super.onTouchEvent(event);
return b;
}
}
地位最低的MyButton:
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Created by feathers on 16-11-13.
*/
public class MyButton extends Button {
private final String TAG = "MyButton";
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i(TAG, "dispatchTouchEvent()");
boolean b = super.dispatchTouchEvent(event);
Log.i(TAG, "dispatchTouchEvent() return");
return b;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "onTouchEvent()");
boolean b = super.onTouchEvent(event);
return b;
}
}
xml如下:
點擊這個myButton:
輸出以下信息:
//**DOWN事件,手按下
//最高一級捕獲到動作,將事件分發給子View進行處理
// A開始分發
I/MyViewGroupA: dispatchTouchEvent()
// ViewGroupA是否要攔截事件,返回true代表攔截,則不會分發給子view
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
// 如果沒有被A攔截,B則會接受到此事件,然後同A相同,分發給子view,看看它們要不要處理
// B開始分發
I/MyViewGroupB: dispatchTouchEvent()
// ViewGroupB是否要攔截這個事件
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return
// 沒有被攔截,則讓MyButton獲取事件,同樣先進性事件分發
I/MyButton: dispatchTouchEvent()
// 因為沒有子View,所以不需要onIntercepTouchEvent()取判斷是否交給子View處理
// 直接調用onTouchEvent()處理事件,但是有時候子View不想處理,如果不想處理,則onTouchEvent()可以返回false
I/MyButton: onTouchEvent()
// MyButton處理結束後,代表B的事件分發結束
I/MyButton: dispatchTouchEvent() return
// MyButton結束後,B也結束了
I/MyViewGroupB: dispatchTouchEvent() return
// 最後ViewGroupA的事件分發同樣也結束了
I/MyViewGroupA: dispatchTouchEvent() return
//**UP事件,手抬起
I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return
I/MyButton: dispatchTouchEvent()
I/MyButton: onTouchEvent()
I/MyButton: dispatchTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent() return
I/MyViewGroupA: dispatchTouchEvent() return
當我們將事件攔截在ViewGroupB中會出現什麼情況呢?
將ViewGroupB的onInterceptTouchEvent()返回值改為true
再來看log:
// GroupA給子View分發事件
I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
// GroupB給子View分發事件
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return
// 這裡發現onInterceptTouchEvent()的返回值為true,即需要攔截事件,此時ViewGroupB發現事件被攔截了,那麼它自己就會處理事件
I/MyViewGroupB: onTouchEvent() // 調用onTouchEvent()處理事件
// B分發完成
I/MyViewGroupB: dispatchTouchEvent() return
// B分發完成後發現 A又調用了onTouchEvent()處理了事件,這是因為onTouchEvent()返回了false,即B雖然根據事件進行了處理,但是並沒有消耗掉事件,這稱為事件回傳。
// 前面的MyButton處理事件後B沒有調用onTouchEvent()的原因在於MyButton將事件消耗掉了,所以可以理解為事件被吃掉了,沒有事件可以回傳。
I/MyViewGroupA: onTouchEvent()
I/MyViewGroupA: onTouchEvent() return
// A分發完成
I/MyViewGroupA: dispatchTouchEvent() return
既然dispatchTouchEvent()決定權這麼大,那我們將dispatchTouchEvent()置為false會不會就代表這個事件不被處理了呢?
把ViewGroupView的dispatchTouchEvent()置為false:
LOg如下:
I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: dispatchTouchEvent() return
// A發現B理都不理它,直接自己處理了
I/MyViewGroupA: onTouchEvent()
I/MyViewGroupA: onTouchEvent() return
I/MyViewGroupA: dispatchTouchEvent() return
使用Material Design 需要api21,即Lollipop/5.0以上 Material Design 為應用提供了:一個新的主題,一些組合Vi
1、為什麼需要異步加載。因為我們都知道在Android中的是單線程模型,不允許其他的子線程來更新UI,只允許UI線程(主線程更新UI),否則會多個線程都去更新UI會造成U
本文實例講述了Android實現兩個ScrollView互相聯動的同步滾動效果代碼。分享給大家供大家參考,具體如下:最近在做一個項目,用到了兩個ScrollView互相聯
預制APK有以下4種情況: 1, 如何將帶源碼的 APK 預置進系統? 2, 如何將無源碼的APK預置進系統? 3, 如何預置APK使得用戶可以卸載,恢復出廠設置時不能恢