如何判定触摸一个视图是长按还是点击
首先,支持长按和点击的视图一定是从Down开始就消费事件,在不设置Touch监听器OnTouchListener的情况下,每个事件都会进入onTouchEvent方法。
当一个视图设置了长按监听器,在Flag中会增加LONG_CLICKABLE标志。View内部静态类ListenerInfo集合了与View相关的各类监听。
public void setOnLongClickListener(@Nullable OnLongClickListener l) {
if (!isLongClickable()) {
setLongClickable(true);
}
getListenerInfo().mOnLongClickListener = l;
}
Down事件时,会调用一个checkForLongClick方法,向主线程延迟发送一个Runnable。
private void checkForLongClick(int delayOffset, float x, float y) {
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();
postDelayed(mPendingCheckForLongPress,
ViewConfiguration.getLongPressTimeout() - delayOffset);
}
}
延迟时间即系统认为多久算长按事件的时间,如果期间手指一直在触屏,当到达该时间时,主线程调度该任务,run方法,将触发performLongClick方法,系统认为这是一次长按事件。
public boolean performLongClick(float x, float y) {
mLongClickX = x;
mLongClickY = y;
final boolean handled = performLongClick();
mLongClickX = Float.NaN;
mLongClickY = Float.NaN;
return handled;
}
手指还在触摸时,就会调用长按监听器的onLongClick方法,如果未达到时间,手指已经离开屏幕,Up事件,此时,如果还没有执行过Runnable,将会调用removeCallbacks方法移除该任务,确保手指离开后不会再触发长按Runnable,同时,执行performClick方法,系统认为这是一次点击事件。
任重而道远
网友评论