Onclick 事件的触发条件
先来废话一下。
- setOnClickListener
- View 没有重写 OnTouchEvent ( 默认情况下 所有触摸事件返回都是clickable,也就是如果View 是可点击的,那么它会消耗一切事件)
- 手指没有移动出View的范围。
- 有抬起动作
为什么手指移出 View 的范围,不会触发OnClick?
onTouchEvent Move 动作处理:
case MotionEvent.ACTION_MOVE:
// Be lenient about moving outside of buttons
if (!pointInView(x, y, mTouchSlop)) {
// Outside button
// Remove any future long press/tap checks
removeTapCallback();
removeLongPressCallback();
if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
}
break;
上面的代码,当pointInView(x, y, mTouchSlop)为false 的时候 ,也就是手指移出View范围,setPressed(false),也就是设置取消了Pressed状态。
而Onclick 事件是在Up 事件中触发的。
case MotionEvent.ACTION_UP:
boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
if (!focusTaken) {
// Use a Runnable and post this rather than calling
// performClick directly. This lets other visual state
// of the view update before click actions start.
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClick();
}
}
}
代码逻辑也很简单:手机抬起时,只要是处于Pressed 状态,就会触发performClick() ,也就是回调 onClick 。
如何实现 手指移出View后,仍然触发点击事件。
可以重写onTouchEvent 方法, 手动设置 View 的Press 状态。
public class TouchView extends TextView {
public TouchView(Context context) {
super(context);
}
public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TouchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean result = super.dispatchTouchEvent(event);
Log.e("touch_tag"," TouchView dispatchTouchEvent " + MotionEvent.actionToString(event.getAction()) + " result = "+ result);
return result;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean result = super.onTouchEvent(event);
Log.e("touch_tag"," TouchView onTouchEvent " + MotionEvent.actionToString(event.getAction()) + " result = "+ result);
Log.e("touch_tag"," MainActivity isPressed" + isPressed());
//手动设置 pressed ,手指移出View 后,仍可以接收到 onClick 事件
setPressed(true);
return result;
}
}