public boolean dispatchTouchEvent(MotionEvent event) {
...
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
// 判断有没有设置onTouchListener 并且view是否是enable
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
// onTouch返回false 调用onTouchEvent处理
if (!result && onTouchEvent(event)) {
result = true;
}
}
...
return result;
}
在View的dispatchEvent里面会判断用户如果设置了onTouchListener,并且view enable属性为true,就会调用onTouch方法,如果onTouch返回true ,则不会再去调用onTouchEvent();
在view的daipatchTouchEvent()中,当有事件来临时如果onTouchEventListener不为空,并且view enable为true时,就会调用onTouch() 所以当点击某个按钮又抬起时 会调用两次onTouch, down事件一次,up事件一次,如果有滑动屏幕时,会调用多次,因为会一直产生move事件
public boolean onTouchEvent(MotionEvent event) {
...
//主要看这一段
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
...
if (!clickable) {
removeTapCallback();
removeLongPressCallback();
mInContextButtonPress = false;
mHasPerformedLongPress = false;
mIgnoreNextUpEvent = false;
break;
}
.....
// mHasPerformedLongPress 当onLongClick()返回true时,将该属性置为true
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
// 将长按计时取消
removeLongPressCallback();
if (!focusTaken) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
// 处理onClick()
if (!post(mPerformClick)) {
performClickInternal();
}
}
}
......
break;
case MotionEvent.ACTION_DOWN:
if (event.getSource() == InputDevice.SOURCE_TOUCHSCREEN) {
mPrivateFlags3 |= PFLAG3_FINGER_DOWN;
}
mHasPerformedLongPress = false;
// 开始长按计时
if (!clickable) {
checkForLongClick(
ViewConfiguration.getLongPressTimeout(),
x,
y,
TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__LONG_PRESS);
break;
}
.....
return true;
}
}
在onTouchEvent()中,当down事件来时,会开始长按计时
private void checkForLongClick(long delay, float x, float y, int classification) {
if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE || (mViewFlags & TOOLTIP) == TOOLTIP) {
mHasPerformedLongPress = false;
//创建一个计时任务
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
mPendingCheckForLongPress.setAnchor(x, y);
mPendingCheckForLongPress.rememberWindowAttachCount();
mPendingCheckForLongPress.rememberPressedState();
mPendingCheckForLongPress.setClassification(classification);
//将任务post进Handler
postDelayed(mPendingCheckForLongPress, delay);
}
}
//计时任务run()
@Override
public void run() {
if ((mOriginalPressedState == isPressed()) && (mParent != null)
&& mOriginalWindowAttachCount == mWindowAttachCount) {
recordGestureClassification(mClassification);
//调用onLongClick() 返回true时 将mHasPerformedLongPress置为true
if (performLongClick(mX, mY)) {
mHasPerformedLongPress = true;
}
}
}
所以onLongClick是在手指触摸屏幕之时开始计时,当到达时间后触发onLongClick() ,onLongClick()返回true后将mHasPerformedLongPress改为true
在Up事件处理时会去判断 如果onLongClick如果没有被触发或者onLongClick返回false,将长按计时取消 然后去触发onClick