1. 程式人生 > >android自定義控制元件事件的傳遞

android自定義控制元件事件的傳遞

  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事件之間的關係:
            先貫穿以下順序,不多說先上程式碼首先是設定一個touch監聽,之後再View中:
@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,不會消耗此事件
後兩條結論是通過分析原始碼所得來的:這裡就不分析原始碼了,可以自己去驗證,希望對小夥伴們有幫助。有錯的地方可以留言指正。謝謝