Android觸摸事件和傳遞機制

觸摸事件類型

MotionEvent.ACTION_DOWN: 手指按下的操作
MotionEvent.ACTION_MOVE:手指頭按下未抬起 并且有移動的操作
MotionEvent.ACTION_UP:手指離開手機屏幕的操作

1.以上操作 down 和 up 為一次完整的操作,是不唏噓的,move看情況了。

事件傳遞的三個階段

  1. 分發(fā)
    對應的dispatchTouchEvent方法。所有觸摸時間 通過這個方法開始分發(fā)。
    返回 true 標識事件被消費掉,停止分發(fā),如果當前試圖為viewGroup或是她的子類,那么會調(diào)用
    onInterceptTouchEvent 方法來判定是否攔截。
  2. 攔截
    onInterceptTouchEvent 只存在于ViewGroup或者她的子類中,activity和其包含的view中均沒有該方法。返回true 標識攔截時間 停止分發(fā),不傳遞給子視圖,交給自身的 onTouchEvent時間進行消費,返回false或者 super.onInterceptTouchEvent 標識不攔截,傳遞給子視圖。
    3.消費
    onTouchEvent,該方法返回true 標識可以處理對應時間,時間不傳遞回給父視圖。false標識傳遞給父視圖的onTouchEvent進行處理

安卓系統(tǒng)中擁有事件處理能力的類:

  • Activity:dispatchTouchEvent 和onTouchEvent 兩個方法
  • ViewGroup:dispatchTouchEvent 和onTouchEvent 和onInterceptTouchEvent 三個
  • view:dispatchTouchEvent 和onTouchEvent 兩個方法

View的事件傳遞機制

1.我們來自定義一個view如下:

/**

  • Created by Administrator on 2018/1/8.
    */

public class MyTextview extends android.support.v7.widget.AppCompatTextView {
private static final String Tag = "MyTextview";

public MyTextview(Context context) {
    super(context);
}

public MyTextview(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {


    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "dispatchTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "dispatchTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "dispatchTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "dispatchTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.dispatchTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "onTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "onTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "onTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "onTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

}
如上所示。。
2.新建一個activity 設計點擊事件 和 觸摸事件
public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {
private TextView view;
private static final String Tag = "MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    view = findViewById(R.id.text_view);
    view.setOnClickListener(this);
    view.setOnTouchListener(this);

}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {


    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "dispatchTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "dispatchTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "dispatchTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "dispatchTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.dispatchTouchEvent(event);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "onTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "onTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "onTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "onTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.text_view:
            Log.e(Tag, "onclick");
            break;

        default:
            break;
    }
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {

    switch (view.getId()) {
        case R.id.text_view:
            switch (motionEvent.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.e(Tag, "Mytextview onTouch down");
                    break;
                case MotionEvent.ACTION_MOVE:
                    Log.e(Tag, "Mytextview onTouch move");
                    break;
                case MotionEvent.ACTION_UP:
                    Log.e(Tag, "Mytextview onTouch up");
                    break;

                default:
                    break;
            }
            break;
        default:
            break;
    }
    return false;
}

}
運行程序 打印log顯示:
01-08 15:53:14.331 9124-9124/com.example.administrator.touchevent E/MainActivity: dispatchTouchEvent down
01-08 15:53:14.331 9124-9124/com.example.administrator.touchevent E/MyTextview: dispatchTouchEvent down
01-08 15:53:14.331 9124-9124/com.example.administrator.touchevent E/MainActivity: Mytextview onTouch down
01-08 15:53:14.331 9124-9124/com.example.administrator.touchevent E/MyTextview: onTouchEvent down
01-08 15:53:14.549 9124-9124/com.example.administrator.touchevent E/MainActivity: dispatchTouchEvent up
01-08 15:53:14.549 9124-9124/com.example.administrator.touchevent E/MyTextview: dispatchTouchEvent up
01-08 15:53:14.549 9124-9124/com.example.administrator.touchevent E/MainActivity: Mytextview onTouch up
01-08 15:53:14.549 9124-9124/com.example.administrator.touchevent E/MyTextview: onTouchEvent up
01-08 15:53:14.550 9124-9124/com.example.administrator.touchevent E/MainActivity: onclick

綜上:

  • 觸摸事件 是從dispatchTouchEvent 開始,如果不進行人為干預的話事件會向內(nèi)不傳遞,到達最內(nèi)層的view是 由 本身onTouchEvent時間處理,如果該方法能消費掉改時間 返回true,負責返回 false,此時事件重新像3外層傳遞。并有外層的view的 onTouchEvent 處理,以此類推。
  • 事件傳遞向內(nèi)層過程中 提前被消費掉,則內(nèi)層view無法收到這個事件。
  • onTocuh方法執(zhí)行完后 才會執(zhí)行 onclick事件。

viewGroup的事件傳遞機制

public class MyLayout extends RelativeLayout {

private static final String Tag = "MyLayout";

public MyLayout(Context context) {
    super(context);
}

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

@Override
public boolean dispatchTouchEvent(MotionEvent event) {


    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "dispatchTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "dispatchTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "dispatchTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "dispatchTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.dispatchTouchEvent(event);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "onInterceptTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "onInterceptTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "onInterceptTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "onInterceptTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.e(Tag, "onTouchEvent down");
            break;
        case MotionEvent.ACTION_MOVE:
            Log.e(Tag, "onTouchEvent move");
            break;
        case MotionEvent.ACTION_UP:
            Log.e(Tag, "onTouchEvent up");
            break;
        case MotionEvent.ACTION_CANCEL:
            Log.e(Tag, "onTouchEvent cacel");
            break;
        default:
            break;
    }
    return super.onTouchEvent(event);
}

}
將這個布局設為最外層布局,依舊打印log信息:
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MainActivity: dispatchTouchEvent down
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MyLayout: dispatchTouchEvent down
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MyLayout: onInterceptTouchEvent down
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MyTextview: dispatchTouchEvent down
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MainActivity: Mytextview onTouch down
01-08 16:13:06.057 14539-14539/com.example.administrator.touchevent E/MyTextview: onTouchEvent down
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MainActivity: dispatchTouchEvent up
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MyLayout: dispatchTouchEvent up
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MyLayout: onInterceptTouchEvent up
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MyTextview: dispatchTouchEvent up
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MainActivity: Mytextview onTouch up
01-08 16:13:06.143 14539-14539/com.example.administrator.touchevent E/MyTextview: onTouchEvent up
01-08 16:13:06.145 14539-14539/com.example.administrator.touchevent E/MainActivity: onclick

  • 觸摸事件傳遞順序,Activity到viewGroup,再有ViewGropup傳遞到子view
  • viewGroup 通過onInterceptTouchEvent進行攔截,返回 true 不會傳遞給 子view,false 則傳遞給子view
  • 子view對事件進行消費后,viewGroup接收不到任何事件。

不要崇拜我。。。。。。。。哈哈哈哈哈哈。。。。。。。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容