1. 程式人生 > >觸控[0] 觸控事件傳遞機制

觸控[0] 觸控事件傳遞機制

【參考連結】

開發藝術探索


1.

涉及到的類和方法主要有

ViewGroupdispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()

ViewdispatchTouchEvent()onInterceptTouchEvent()onTouchEvent()


一般來說,在自定義View/ViewGroup的時候,不修改dispatchTouchEvent(),只重寫onInterceptTouchEvent()(不保留super呼叫)和onTouchEvent()(保留super呼叫,如果需要響應OnLongClickListener/OnClickListener

的話)

2.

如果設定了OnTouchListener,則會先執行OnTouchListener。並且只有OnTouchListener返回false才會再執行onTouchEvent()

3.

如果子View能夠收到ACTION_DOWN但其OnTouchListener/onTouchEvent()返回了false,則其不會再收到後續的ACTION_MOVEACTION_UP等。

4.

可以在子View/ViewGroupOnTouchListener/onTouchEvent()ACTION_DOWN中使用getParent().requestDisallowInterceptTouchEvent()

來請求父ViewGroup不要中斷傳遞後續的ACTION_MOVEACTION_UP等。(此時也不會執行父ViewGrouponInterceptTouchEvent()

注意這隻有在子View/ViewGroup能夠收到ACTION_DOWN的前提下才能起作用。

5

只有能夠執行到Viewsuper.onTouchEvent()才能夠觸發onLongClickListener/onClickListener

如果設定了onLongClickListener,在ACTION_DOWN超時後就會觸發onLongClickListener

只有當onLongClickListener返回false

,在ACTION_UP後才會繼續觸發onClickListener

可以使用如下的程式碼來修改驗證

public class MyFrameLayout extends FrameLayout {

//public static final intACTION_DOWN = 0;
//public static finalint ACTION_UP = 1;
//public static finalint ACTION_MOVE = 2;
//public static finalint ACTION_CANCEL = 3;

public static final String[] ACTIONS={"ACTION_DOWN", "ACTION_UP", "ACTION_MOVE", "ACTION_CANCEL"};

public
MyFrameLayout(Context context) {
super(context);
init();
}

public MyFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

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

public void init(){

setOnTouchListener(
new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.e(
"shadowfaxghh", "MyFrameLayout OnTouchListener "+ACTIONS[motionEvent.getAction()]);
return false;
}
})
;

setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Log.e(
"shadowfaxghh", "MyFrameLayout onLongClick");
return false;
}
})
;

setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Log.e(
"shadowfaxghh", "MyFrameLayout onClick");
}
})
;

}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(
"shadowfaxghh", "MyFrameLayout dispatchTouchEvent "+ACTIONS[ev.getAction()]);
return super
.dispatchTouchEvent(ev);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(
"shadowfaxghh", "MyFrameLayout onInterceptTouchEvent "+ACTIONS[ev.getAction()]);

//return super.onInterceptTouchEvent(ev);
//return false;
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
return false;
default
:
return true;
}

}

@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(
"shadowfaxghh", "MyFrameLayout onTouchEvent "+ACTIONS[event.getAction()]);

super
.onTouchEvent(event);//for onLongClick/onClick

return true;
}
}

public class MyTextView extends TextView {

public static final String[] ACTIONS={"ACTION_DOWN", "ACTION_UP", "ACTION_MOVE", "ACTION_CANCEL"};

public
MyTextView(Context context) {
super(context);
init();
}

public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

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

public void init(){

setOnTouchListener(
new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.e(
"shadowfaxghh", "MyTextView OnTouchListener "+ACTIONS[motionEvent.getAction()]);
return false;
}
})
;

setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
Log.e(
"shadowfaxghh", "MyTextView onLongClick");
return false;
}
})
;

setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Log.e(
"shadowfaxghh", "MyTextView onClick");
}
})
;
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(
"shadowfaxghh", "MyTextView dispatchTouchEvent");
return super
.dispatchTouchEvent(ev);
}

//@Override
//public booleanonInterceptTouchEvent(MotionEvent ev) {
//
//Log.e("shadowfaxghh", "MyTextViewonInterceptTouchEvent");
//
////return super.onInterceptTouchEvent(ev);
//return false;
//}

@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(
"shadowfaxghh", "MyTextView onTouchEvent "+ACTIONS[event.getAction()]);

super
.onTouchEvent(event);//for onLongClick/onClick

switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
getParent().requestDisallowInterceptTouchEvent(
true);
break;
default
:
break;
}

return true;
}
}