为了防止该布局发生触摸,您有多种选择:
1)设置OnTouchListener,它总是返回true。
2)重写dispatchTouchEvent(MotionEvent event)以始终返回true
UPD:好吧,通常你必须设置 OnTouchListener,它总是返回 true,正如我之前所说,以防止调用其他视图onTouch
,但是对于 ScrollView 来说就完全是另外一个故事了。
首先我会告诉你如何dispatchTouchEvent
作品。它开始将事件从根视图分派到其子视图,这意味着dispatchTouchEvent
父级称为BEFORE dispatchTouchEvent
它的孩子们。
Then in ViewGroup.dispatchTouchEvent()
有一段代码
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
它决定是否应该拦截此触摸事件,这意味着如果intercepted
flag 为 true,则该视图将拦截所有连续事件。并且在ScrollView
onInterceptTouchEvent
实现拦截正在执行垂直滚动的操作。
所以我的第一个想法是设置FLAG_DISALLOW_INTERCEPT
到您的自定义视图的父级以禁止这种拦截事件的机会,但这个想法失败了,因为下面的代码行ViewGroup
:
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Throw away all previous state when starting a new touch gesture.
// The framework may have dropped the up or cancel event for the previous gesture
// due to an app switch, ANR, or some other state change.
cancelAndClearTouchTargets(ev);
resetTouchState();
}
所以这意味着之后MotionEvent.ACTION_DOWN
所有状态都被清除(也是如此FLAG_DISALLOW_INTERCEPT
也被清除)。
所以最终的解决方案非常简单
public class PreventingTouchEventView extends View {
public PreventingTouchEventView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.RED);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (getParent() != null && event.getAction() == MotionEvent.ACTION_DOWN) {
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(event);
}
}
这会提高FLAG_DISALLOW_INTERCEPT
就在第一个之后MotionEvent.ACTION_DOWN
,这将不允许父级进一步拦截未来的操作。
但请注意,如果您的父母认为在MotionEvent.ACTION_DOWN
并拦截这个事件,那么你就无能为力,因为你的父母dispatchTouchEvent
在你之前被调用dispatchTouchEvent
.