Androidイベント配信メカニズムの概要


Androidイベント配信メカニズム
 
Android通常view(ViewGroupを除く)とactivityでは、主にイベントを処理する2つの方法があります.
public boolean dispatchTouchEvent(MotionEvent ev) //     
public boolean onTouchEvent(MotionEvent event)     //     

 
View Groupでは、もう1つの方法があります.
public boolean onInterceptTouchEvent(MotionEvent ev) //     

 
1、activityでは、イベント配信->イベント処理の順で、イベント配信時にイベント(return true)が消費された場合、イベント処理はイベントを受信しません.
 
public class MainActivity extends Activity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//     
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_MOVE) {
 System.out.println("dispatchTouchEvent-->ACTION_MOVE");
return true; //       ,     
}
return super.dispatchTouchEvent(ev);
}
//     
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("onTouchEvent-->ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("onTouchEvent-->ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("onTouchEvent-->ACTION_UP");
break;
}
return super.onTouchEvent(event);
}
}

 
上記のコードの結果:
onTouchEvent-->ACTION_DOWN
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
dispatchTouchEvent-->ACTION_MOVE
onTouchEvent-->ACTION_UP
 
結果的に:ACTION_MOVEはonTouchEventには入っていません.dispatchTouchEventで判断したので、ACTION_MOVEではreturn trueはこのイベントを消費することを示し、イベントはonTouchEventに配布されず、すべてのonTouchEventはACTION_しか受信できないDOWNとACTION_UPイベント.
 
2、通常viewのイベント配布
 
通常のviewのイベントはdispatchTouchEventによってイベントが配布され、イベントの順序はACTION_である.DOWN、ACTION_MOVE、ACTION_UPは、あるイベントが消費された場合、他のイベントは実行されません.配布イベントはonTouchによって最初に受信され、onTouchがtrueに戻った場合、イベントが消費されたことを示すと、viewのclickイベントは実行されません.
 
mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  System.out.println("onTouch..."+event.getAction());
return true;  //       ,   click      
}
});
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//      onTouch      ,       
System.out.println("onClick...");
}
});

 
 
3、View Groupのイベント配布:
ViewGroupのイベント配信は少し面倒で、カスタマイズされたLinearLayout:MyLayoutを例に挙げます.
イベントが発生すると、まずMyLayoutのdispatchTouchEventがイベントの配信を行い、その後MyLayoutのonInterceptTouchEventブロックイベント1、onInterceptTouchEventがreturn trueがそのイベントのブロックを表し、MyLayoutで残りのイベントを処理し、イベントは引き続きMyLayoutが配信し、配信メカニズムは上記のviewイベント配信メカニズムと同じである.しかし、今回の配布はサブviewに配布することも考えられず、onInterceptTouchEventにも行かない.システムはこのイベントをMyLayoutがブロックしたことを知っているので、MyLayoutで直接処理する.
2、MyLayoutのonInterceptTouchEventがfalse(デフォルトではfalse[1]を返す)を返すと、イベントをブロックしないことを示し、MyLayoutのサブview(Buttonを例に)のdispatchTouchEventがイベントを配信し始める.配信メカニズムは上記のviewイベント配信メカニズムである.
public class MyLayout extends LinearLayout {
	public MyLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		System.out.println("dispatchTouchEvent");
		return super.dispatchTouchEvent(ev);
	}
	
	
	//     ,    MyLayout dispatchTouchEvent       
	//    MyLayout onInterceptTouchEvent    
	//   return true       ,  MyLayout   
	//         MyLayout    ,           
	//  view,    onInterceptTouchEvent,        
	//     MyLayout    ,     MyLayout   
	
	//  demo     :
	//    down、move、up :
	// dispatchTouchEvent
	// onInterceptTouchEvent
	// action_down...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_up...
	
	//    :
	// dispatchTouchEvent
	// onInterceptTouchEvent
	// action_down...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_up...
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		System.out.println("onInterceptTouchEvent");
		if(ev.getAction() == MotionEvent.ACTION_DOWN) {
			return true;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("action_down...");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("action_up...");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("action_move...");
			break;
		}
		return true;
	}
}
実行結果:第1セットdown、move、up:dispatchTouchEvent onInterceptTouchEvent action_down... dispatchTouchEvent action_move... dispatchTouchEvent action_move... dispatchTouchEvent action_move... dispatchTouchEvent action_up... もう1つ:dispatchTouchEvent onInterceptTouchEvent action_down... dispatchTouchEvent action_move... dispatchTouchEvent action_move... dispatchTouchEvent action_move... dispatchTouchEvent action_up... MyLinearLayout:
public class MyLinearLayout extends LinearLayout{
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;  
//     true,       ,     view  ,     view dispachTouchEvent onTouch
}
}
MainActivity:
public class MainActivity extends Activity {
private MyLinearLayout mLayout;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = (MyLinearLayout) findViewById(R.id.layout);
mButton = (Button) findViewById(R.id.click);
mLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("layout touch " + event.getAction());
return false;
}
});
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//    MyLinearLayout        ,        
               System.out.println("button click...");
}
});
}
}
実行結果:layout touch 0注意[1]:ListViewのonInterceptTouchEventはデフォルトでtrueを返し、イベントをブロックしたことを示す.したがってlistViewでのButtonは通常の設定ではクリックできません.