Scrollview的requestDisallowInterceptTouchEvent

时间:2015-09-28 19:33:12

标签: android scrollview ontouchevent android-scrollview google-street-view

我在scrollview中的linearlayout中有一个StreetViewPanoramaView:

  <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollview">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/linear">

            <com.google.android.gms.maps.StreetViewPanoramaView
                android:id="@+id/street_view_panorama"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

                <other views - textviews etc>

        </LinearLayout>

    </ScrollView>

StreetViewPanoramaView允许用户上下左右移动街景摄像机。我希望滚动视图在用户移动相机时停止拦截用户触摸事件。目前,如果用户在StreetViewPanoramaView中移动相机,则scrollview会截取触摸并移动滚动视图。

我尝试了https://mobiarch.wordpress.com/2013/11/21/prevent-touch-event-theft-in-android/中的代码,但它似乎无法正常工作(scrollview仍在处理触摸事件):

      mStreetViewPanoramaView = (StreetViewPanoramaView) findViewById(R.id.street_view_panorama);
        LinearLayout.LayoutParams streetViewLp =
                new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, displaymetrics.widthPixels/3);
        mStreetViewPanoramaView.setLayoutParams(streetViewLp);

        disableTouchTheft(mStreetViewPanoramaView);

public static void disableTouchTheft(View view) {
    view.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            view.getParent().getParent().requestDisallowInterceptTouchEvent(true);
            switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_UP:
                view.getParent().getParent().requestDisallowInterceptTouchEvent(false);
                break;
            }
            return false;
        }
    });
}

编辑:

我尝试过的事情:

我创建了一个自定义视图,并将代码dispatchTouchEvent导入到我的活动代码中:

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        int[] loc = {0, 0};
        mStreetViewPanoramaView.getLocationOnScreen(loc);

        Rect rect = new Rect(loc[0], loc[1] , loc[0] + mStreetViewPanoramaView.getWidth(), loc[1] + mStreetViewPanoramaView.getHeight());


        if (rect.contains((int) event.getRawX(), (int) event.getRawY())) {
            Log.e("stretview", "dispatched");
            return mStreetViewPanoramaView.dispatchTouchEvent(event);
/*            return true;*/

        }else{
            //Continue with touch event
            return super.dispatchTouchEvent(event);
        }
    }

public class CustomStreetViewPanoramaView extends StreetViewPanoramaView {

    public CustomStreetViewPanoramaView(Context context) {
        super(context);
    }

    public CustomStreetViewPanoramaView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomStreetViewPanoramaView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public CustomStreetViewPanoramaView(Context context, StreetViewPanoramaOptions options) {
        super(context, options);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        return false; // Do not intercept touch event, let the child handle it
    }
}

代码似乎是半工作 - 看起来StreetViewParnoramaView将获取视图上半部分的触摸事件,但下半部分不会获得任何触摸事件。

我的完整布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:id="@+id/container"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollview">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:id="@+id/linearlayout">

            <com.example.simon.customshapes.CustomStreetViewPanoramaView
                android:id="@+id/street_view_panorama"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="500dp"
                android:id="@+id/card"
                >
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Hello card"
                    android:layout_gravity="center" />

            </android.support.v7.widget.CardView>

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Save panorama"
                android:padding="8dp"
                android:id="@+id/savepano"/>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/my_recycler_view"
                android:scrollbars="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </android.support.v7.widget.RecyclerView>

        </LinearLayout>
    </ScrollView>

</LinearLayout> 

2 个答案:

答案 0 :(得分:1)

约翰的答案是正确的道路,但仍然没有用 - 这个会起作用

    @Override
public boolean dispatchTouchEvent(MotionEvent event) {

    if (streetView != null) {
        streetView.getGlobalVisibleRect(rect);

        if (rect.contains((int) event.getRawX(), (int) event.getRawY())) {
            event.offsetLocation(-rect.left, -rect.top);
            streetView.dispatchTouchEvent(event);
            return true;

        } else {
            //Continue with touch event
            return super.dispatchTouchEvent(event);
        }
    } else {
        return super.dispatchTouchEvent(event);
    }
}

活动的dispatchTouchEvent并在将事件抵消到streetView后移动事件

答案 1 :(得分:0)

你可以试试以下......

@Override
public boolean dispatchTouchEvent(MotionEvent event) {

    int[] loc = {0, 0};
    mStreetViewPanoramaView.getLocationOnScreen(loc);

    Rect rect = new Rect(loc[0], loc[1] , loc[0] + mStreetViewPanoramaView.getWidth(), loc[1] + mStreetViewPanoramaView.getHeight());


    if (rect.contains((int) event.getRawX(), (int) event.getRawY())) {            
        mStreetViewPanoramaView.dispatchTouchEvent(event);
        return true;

    }else{
        //Continue with touch event
        return super.dispatchTouchEvent(event);
    }
}

这有望检查触摸是否在全视图上并相应处理。