我们有时候会在项目中遇到ScrollView作为父类嵌套其他子控件,这次我在项目中遇到嵌套GridView。且GridView是用来显示静态图标,类似九宫格等。这样正常来显示是没问题的,但我们的需求是在页面自由的上下滑动ScrollView,问题就来了,当我们手指在GridView上面进行上下滑动时,发现父控件ScrollView不动了。这是因为GridView自己消费了滑动事件。
解决方案有很多种,比如在ScrollView中重写onInterceptTouchEvent事件分发,把滑动事件禁止向下分发。这样子控件拿不到滑动事件自然不会消耗该事件。但这样做对某些android手机则失去了作用,甚至会让GridView连点击事件都监听不到了,所以我们都得根据具体需求去寻求最好的解决方案。
我项目中在ScrollView嵌套的子控件比较复杂,需要往下传左右滑动事件,所以不能把滑动事件禁止分发,所以便有了如下的解决方式:(有不对之处请多多指正)
public class MyScrollView extends ScrollView {
<span style="white-space:pre"> </span>private boolean canScroll;
<span style="white-space:pre"> </span>private GestureDetector mGestureDetector;
<span style="white-space:pre"> </span>View.OnTouchListener mGestureListener;
<span style="white-space:pre"> </span>public <span style="font-family: Arial, Helvetica, sans-serif;">MyScrollView</span>(Context context, AttributeSet attrs) {
<span style="white-space:pre"> </span>super(context, attrs);
<span style="white-space:pre"> </span>mGestureDetector = new GestureDetector(new YScrollDetector());
<span style="white-space:pre"> </span>canScroll = true;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public boolean onInterceptTouchEvent(MotionEvent ev) {
<span style="white-space:pre"> </span>if (ev.getAction() == MotionEvent.ACTION_UP)
<span style="white-space:pre"> </span>canScroll = true;// 到用户手指离开屏幕的时候设为true
<span style="white-space:pre"> </span>return mGestureDetector.onTouchEvent(ev)
<span style="white-space:pre"> </span>|| super.onInterceptTouchEvent(ev);//当手指向上或向下滑动时,则进行拦截事件
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>class YScrollDetector extends SimpleOnGestureListener {
<span style="white-space:pre"> </span>@Override
<span style="white-space:pre"> </span>public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
<span style="white-space:pre"> </span>float velocityY) {
<span style="white-space:pre"> </span>if (canScroll) {
<span style="white-space:pre"> </span>if (velocityY < 0) { // 手指向上,屏幕向上滑动
<span style="white-space:pre"> </span>canScroll = true;
<span style="white-space:pre"> </span>} else if (velocityY > 0) { // 手指向下,屏幕向下滑动
<span style="white-space:pre"> </span>canScroll = true;
<span style="white-space:pre"> </span>;
<span style="white-space:pre"> </span>} else {
<span style="white-space:pre"> </span>canScroll = false;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>return canScroll;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}