我有一个容器ViewGroup
,我们在ScrollView
内称之为屏幕。此容器视图托管了许多其他Views
让他们称之为小部件,其中一些人有兴趣阻止ScrollView滚动并使用MotionEvent(例如a) pannable image)
我无法弄清楚要使用的正确的事件拦截策略。 ScrollView
始终在子项之前处理事件,或者子项处理事件但scrollview
已禁用。
如果此视图想要捕获事件,我读到了在子视图中发出getParent().requestDisableInterceptTouchEvent()
,但是他们的onTouchEvent
未被调用,我想是因为ScrollView
事先已经吞没了事件。我想我有两级图层(容器+小部件)阻止了它的工作,我想容器ViewGroup
必须在这里发挥重要作用,但我无法弄清楚哪一个。 ..
我可以在ScrollView's
onInterceptTouchEvent
级别了解容器viewGroup
上的哪个小部件已被触及以决定是否应该拦截?
...或
'小部件' ViewGroup
中的图层会在ScrollView
之前获取该事件,因此我可以致电getParent().onRequestDisableInterceptTouch()
...或者是getParent().getParent().onRequestDisableInterceptTouch()
?
提前致谢
我已经阅读了相关问题,但没有运气...... Handle touch events in ScrollView Android
答案 0 :(得分:9)
经过一夜的可口可乐&调试我设法使这个工作。我会分享解决方案,以防任何人感兴趣,因为我花了很多时间才能让它运行。
我没有设法让它与getParent().onRequestDisableInterceptTouch()
一起运行,我很接近,但是当我拦截父母的触摸时,无法找到让小部件获取滚动所需的MotionEvent的方法,即使外部滚动被正确阻止,内部小部件也不会滚动。
因此解决方案是仅在子项中interceptTouchEvents
,如果子项是可滚动的(已知属性),并且触摸是ACTION_DOWN,则禁用上面两级的scrollview。如果触摸是ACTION_UP,我们启用滚动视图。
要启用/禁用滚动视图,我只是截取触摸事件,并使用标记过滤事件与否。
我做了三个辅助类,一个用于ScrollView,一个用于容器,一个用于小部件:
这个类包装了每个小部件,如果我调用setNeedsScroll(true),那么将拦截触摸,当触摸它时,它将(告诉容器)告诉scrollview禁用它自己。触摸释放后,将重新启用滚动视图。
class WidgetWrapperLayout extends FrameLayout {
private boolean mNeedsScroll=false;
public WidgetWrapperLayout(Context context) {
super(context);
}
/** Called anytime, ie, during construction, to indicate that this
* widget uses vertical scroll, so we need to disable its container scroll
*/
public void setNeedsScroll(boolean needsScroll) {
mNeedsScroll=needsScroll;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mNeedsScroll) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
((SlideLayout)getParent()).setEnableScroll(false);
break;
case MotionEvent.ACTION_UP:
((SlideLayout)getParent()).setEnableScroll(true);
break;
}
return false;
}
return super.onInterceptTouchEvent(ev);
}
}
这是容器,scrollview
的唯一子容器,并包含不同的小部件。它只是为孩子们提供了方法,因此他们可以启用/禁用滚动:
public class ContainerLayout extends FrameLayout {
public ContainerLayout(Context context) {
super(context);
}
public void setEnableScroll(boolean status) {
if (Conf.LOG_ON) Log.d(TAG, "Request enable scroll: "+status);
((StoppableScrollView)getParent()).setScrollEnabled(status);
}
}
最后是一个能够停用的滚动视图。它禁用滚动'old-skool',拦截和阻止事件。
public class StoppableScrollView extends ScrollView {
private String TAG="StoppableScrollView";
private boolean mDisableScrolling=false;
public StoppableScrollView(Context context) {
super(context);
}
/** Enables or disables ScrollView scroll */
public void setScrollEnabled (boolean status) {
if (Conf.LOG_ON) Log.d(TAG, "Scroll Enabled "+status);
mDisableScrolling=!status;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mDisableScrolling) return false;
return super.onInterceptTouchEvent(ev);
}
}
答案 1 :(得分:-1)
在Activity中实现View.OnTouchListener
并将该侦听器添加到ScrollView。然后在onTouchEvent(...)
中返回true。在返回之前,请调用您想要处理该事件的孩子的onTouch
。