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~~~~~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章