android自定義控制元件事件的傳遞
阿新 • • 發佈:2019-01-25
Button button = (Button) findViewById(R.id.btn); button.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { Log.i(TAG,"Button onTouch"+motionEvent.getAction()); return true; } }); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i(TAG,"Button OnClick"); } });
執行列印看效果: 首先執行的事OnTouch事件,之後才走的OnClick事件,當我們OnTouch返回true的時候,執行看效果: 我們發現OnClick事件沒有響應,原因是沒有接收到UP事件。所以我們可以得到以下的結論: 1.控制元件的Listener事件觸發的順序是先onTouch,再onClick。
2.控制元件的onTouch返回true,將會onClick事件沒有了---阻止了事件的傳遞。
返回false,才會傳遞onClick事件(才會傳遞up事件) 下面我們來討論,View本身的onTouch事件和Listener事件還有dispatchTouchEvent事件之間的關係:
@SuppressLint("AppCompatCustomView") public class MyButton extends Button { private static final String TAG = "lang"; public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(TAG,"Button dispatchTouchEvent"); return super.dispatchTouchEvent(event); // return true; } @Override public boolean onTouchEvent(MotionEvent event) { Log.i(TAG,"Button onTouchEvent"); return super.onTouchEvent(event); } }
列印驗證事件傳遞的順序: 這個是走的順序,當我們在
這裡只返回true的時候,我們執行的效果是 也就是是說事件會在這裡終止,但是,當我們這樣的時候: 效果: 所以super.dispatchTouchEvent是實際的分發程式碼,同理,我們的OnTouch也是如此,這裡我們就不驗證了。 但是我們在Listener事件裡面返回true的時候呢? 當: 執行的效果是這樣的: 所以我們可以得到這樣的結論: 1.如果onTouchListener的onTouch方法返回了true,那麼view裡面的onTouchEvent就不會被呼叫了。 順序dispatchTouchEvent-->onTouchListener---return false-->onTouchEvent 2.如果view為disenable,則:onTouchListener裡面不會執行,但是會執行onTouchEvent(event)方法
3.onTouchEvent方法中的ACTION_UP分支中觸發onclick事件監聽
onTouchListener-->onTouch方法返回true,消耗次事件。down,但是up事件是無法到達onClickListener.
onTouchListener-->onTouch方法返回false,不會消耗此事件
後兩條結論是通過分析原始碼所得來的:這裡就不分析原始碼了,可以自己去驗證,希望對小夥伴們有幫助。有錯的地方可以留言指正。謝謝