Android ScrollView嵌套ScrollView,并且嵌套的ScrollView超过屏幕部分

问题:我在ScrollView里面嵌套了一个ScrollView,嵌套的ScrollView超出了屏幕显示部分,需要向下滑动才能看到,当滑动下去找到嵌套的ScrollView时,滑动时并不能触发它的onTouch()事件。

Android的Touch传递机制,这里不详细介绍了,有想了解的,推荐http://blog.csdn.net/chunqiuwei/article/details/41084921,和http://www.infoq.com/cn/articles/android-event-delivery-mechanism/ 这两篇写得都不错,可以借鉴一下。

解决思路:
1. 先是参考的http://mengsina.iteye.com/blog/1707464这一篇文章,主要利用了在onTouch()事件里面写v.getParent().requestDisallowInterceptTouchEvent(true); 这种方法,让父ScrollView不拦截Touch事件,自己来处理。

亲自实验了这个方法,当嵌套的ScrollView不超出屏幕时是可以用的,可是当嵌套的ScrollView超出屏幕时,就不可以了。
代码如下,当touch子ScrollView时,打印出”触摸了第2个ScrollView”,然而并没有成功,结果在后面,全都是打印的”触摸了第1个ScrollView”:
MainActivity.java->onCreate():

//父ScrollView
svParent = (ScrollView) findViewById(R.id.sv_parent);
        svParent.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ViewParent parent = findViewById(R.id.sv_child).getParent();
                parent.requestDisallowInterceptTouchEvent(false);  //允许父类截断
                System.out.println("触摸了第1个ScrollView");
                return false;
            }
        });
        //子ScrollView
        svChild = (ScrollView) findViewById(R.id.sv_child);
        svChild.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                ViewParent parent1 = v.getParent();
                parent1.requestDisallowInterceptTouchEvent(true); //不允许父类截断
                System.out.println("触摸了第2个ScrollView");
                return false;
            }
        });

结果截图:
结果

从这个结果来看,Touch事件,没有传递到嵌套的ScrollView上来,应该是被上层的ViewGroup截获,或者是传下去被下面的View消费掉了,没再传上来。

2.接下来,就是想让这个嵌套的ScrollView截获传递过来的Touch事件,不再分发下去了。所以想到重写ScrollView的onInterceptTouchEvent(),让它返回true,让这个嵌套的ScrollView截获这个Touch事件(注意:onInterceptTouchEvent()返回true,表示截获这个Touch事件;返回false,表示不搭理这个Touch事件)。

自定义ScrollView CustomScrollView.java:

package com.tudou.scrollviewnested;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * Created by Administrator on 2016-08-14.
 */
public class CustomScrollView extends ScrollView {
    public CustomScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        System.out.println("第2个ScrollView:dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        System.out.println( "第2个ScrollView: onInterceptTouchEvent: ");
//        return super.onInterceptTouchEvent(ev);
     boolean flag = false;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_UP:
                flag = super.onInterceptTouchEvent(ev);
                break;
            case MotionEvent.ACTION_MOVE:
                flag = true;
                break;
        }

        return flag;

    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        System.out.println( "第2个ScrollView: onTouchEvent: ");
        return super.onTouchEvent(ev);
    }
}

在上面的代码里面可以看到,onInterceptTouchEvent()函数,我让它直接返回了true。再看一下结果,看看调用顺序哈。
结果截图:
2

从结果上可以看出这几个函数的调用顺序:
1. 是CustomScrollView里面的dispatchTouchEvent()
2. 是CustomScrollView里面的onInterceptTouchEvent()
3. 是MainActivity里面的svChild.setOnTouchListener->onTouch()事件
4. 是CustomScrollView里面的onTouchEvent()

^_^ OK~~~~~~~

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页