如何监听一个View的长按事件
view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// TODO
return false;
}
});
- onLongClick 的返回值默认是false,这样写会有什么问题呢。如果这个时候我们同时监听了View的点击事件,触发了长按事件后,点击事件也同样会触发。很显然这不是我们想要的。
- 如果我们把onLongClick 的返回值设值成true后,长按事件就消费了此次的事件,点击事件就不会触发。
- 针对上诉问题我们应该怎么处理呢?
tv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
tv.setTag("longclick");
copy((TextView) v);
return true;
}
});
tv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (parentView!=null && tv.getTag()==null){
parentView.performClick();
}
if (tv.getTag()!=null){
tv.setTag(null);
}
}
return false;
}
});
具体原理我们来简单看一下 View事件分发的源码 ,具体可参考)android 事件分发机制
public boolean onTouchEvent(MotionEvent event) {
// ...省略
// 重点
if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
switch (action) {
case MotionEvent.ACTION_UP:
// 1.mHasPerformedLongPress跟长按有关,默认为false,
// 只有 onLongClick回调方法返回true时,该值才为true
if (!mHasPerformedLongPress && !mIgnoreNextUpEvent){
removeLongPressCallback();
if (!focusTaken) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClickInternal();
}
}
}
break;
}
return true;
}
return false;
}
结论:
- onLongClick返回值设置成true后,长按事件就不会在onTouchEvent里就不会触发 点击事件(performClickInternal)
- 把点击事件放在 onTouch里手动触发,并且通过tv的tag屏蔽掉长按事件