我无法弄清楚要使用的正确的事件拦截策略. ScrollView始终在子项之前处理事件,或者子项处理事件但禁用scrollview.
我读到了如果这个视图想要捕获事件但在子视图中发出getParent().requestDisableInterceptTouchEvent(),但是他们的onTouchEvent没有被调用,我想是因为ScrollView事先已经吞没了事件.我想我有两级图层(容器小部件)的事实阻止了它的工作,我想容器ViewGroup必须在这里发挥重要作用,但我无法弄清楚哪一个……
我可以知道,在ScrollView的onInterceptTouchEvent级别,触摸了容器viewGroup上的哪个小部件来决定是否应该拦截?
要么…
ViewGroup中的’widget’层如何在ScrollView之前获取事件,因此我可以调用getParent().onRequestDisableInterceptTouch()…或者是getParent().getParent().onRequestDisableInterceptTouch()?
提前致谢
我已经阅读了相关问题,但没有运气……
Handle touch events in ScrollView Android
解决方法
我没有设法让它运行getParent().onRequestDisableInterceptTouch(),我很接近,但是一旦我拦截了父项上的触摸,找不到让子小部件获取滚动所需的MotionEvent的方法,所以即使外部滚动被正确阻止,内部小部件也不会滚动.
所以解决方法是仅在子节点中拦截触发事件,如果子节点是可滚动的(已知属性),并且触摸是ACTION_DOWN,则禁用上面两级的scrollview.如果触摸是ACTION_UP,我们启用scrollview.
要启用/禁用滚动视图,我只是拦截触摸事件,并使用标志过滤事件与否.
我做了三个辅助类,一个用于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); } }