ScrollView 中的 MapView?

问题描述 投票:0回答:10

我希望在 ScrollView 中有一个 MapView,但是当我尝试滚动地图时,ScrollView 优先!有没有办法在地图内滚动时优先考虑 MapView,否则优先考虑 ScrollView?

谢谢!

android google-maps android-maps
10个回答
104
投票

我已经遇到同样的问题10天了,但几分钟前我得到了解决方案! 这是解决方案。 我制作了一个自定义 MapView 并像这样重写 onTouchEvent() 。

@Override
public boolean onTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
        // Disallow ScrollView to intercept touch events.
        this.getParent().requestDisallowInterceptTouchEvent(true);
        break;

    case MotionEvent.ACTION_UP:
        // Allow ScrollView to intercept touch events.
        this.getParent().requestDisallowInterceptTouchEvent(false);
        break;
    }

    // Handle MapView's touch events.
    super.onTouchEvent(ev);
    return true;
}

58
投票

一种更好/更简单的方法来做到这一点,无需操纵单独的触摸事件。 如果您使用 MapView,这将起作用:

  @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        /**
         * Request all parents to relinquish the touch events
         */
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(ev);
    }

全班:

public class CustomMapView extends MapView {

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

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

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

    public CustomMapView(Context context, GoogleMapOptions options) {
        super(context, options);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        /**
         * Request all parents to relinquish the touch events
         */
        getParent().requestDisallowInterceptTouchEvent(true);
        return super.dispatchTouchEvent(ev);
    }
}

如果您使用的是 MapFragment,那么您可以将片段放入自定义视图中,然后在

dispatchTouchEvent()
中进行
requestDisallowInterceptTouchEvent
调用。


21
投票

制作你自己的地图并使用它。它完全适合我。

public class CustomMapView extends MapView {

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

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
    case MotionEvent.ACTION_UP:
        System.out.println("unlocked");
        this.getParent().requestDisallowInterceptTouchEvent(false);
        break;
    case MotionEvent.ACTION_DOWN:
        System.out.println("locked");
        this.getParent().requestDisallowInterceptTouchEvent(true);
        break;
    }
    return super.dispatchTouchEvent(ev);
}} 

在布局 xml 中,

<com.yourpackage.xxxx.utils.CustomMapView
                android:id="@+id/customMap"
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                />

16
投票

对于那些想要完整工作代码的人。在这里

自定义地图视图类

public class CustomMapView extends MapView {

private ViewParent mViewParent;
public CustomMapView(Context context) {
    super(context);
}

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

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

public CustomMapView(Context context, GoogleMapOptions options) {
    super(context, options);
}

public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
    mViewParent = viewParent;
}

@Override
public boolean onInterceptTouchEvent(final MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(true);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_UP:
            if (null == mViewParent) {
                getParent().requestDisallowInterceptTouchEvent(false);
            } else {
                mViewParent.requestDisallowInterceptTouchEvent(false);
            }
            break;
        default:
            break;
    }

    return super.onInterceptTouchEvent(event);
  }
}

活动布局xml

  <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <location.to.your.CustomMapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="250dp"
         />

</ScrollView>

在您的 Activity 或片段中实例化自定义地图类

       CustomMapView mapView = (CustomMapView) findViewById(R.id.mapView);

就这样享受吧


9
投票

您可以像这样创建自定义 MapView:

public class CustomMapView extends MapView {

    private MapFragment.ControlLock mCallbackControl;

    public CustomMapView(Context context) {
        this(context, null);
    }

    public CustomMapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    public CustomMapView(Context context, GoogleMapOptions options) {
        super(context, options);
    }

    public void setCallback(MapFragment.ControlLock callbackControl) {
        this.mCallbackControl = callbackControl;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                System.out.println("unlocked");
                mCallbackControl.unlock(); /* Interface */
                break;
            case MotionEvent.ACTION_DOWN:
                System.out.println("locked");
                mCallbackControl.lock(); /* Interface */
                break;
        }

        return super.dispatchTouchEvent(event);
    }
}

8
投票

我尝试过重写 MapView.onTouchEvent(...),但它对我不起作用。 这是运行良好的代码(覆盖 MapView.onInterceptTouchEvent(...)):

public class MyMapView extends MapView {
    private ViewParent mViewParent;

//add constructors here

    public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
            mViewParent = viewParent;
    }

    @Override
        public boolean onInterceptTouchEvent(final MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (null == mViewParent) {
                        getParent().requestDisallowInterceptTouchEvent(true);
                    } else {
                        mViewParent.requestDisallowInterceptTouchEvent(true);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (null == mViewParent) {
                        getParent().requestDisallowInterceptTouchEvent(false);
                    } else {
                        mViewParent.requestDisallowInterceptTouchEvent(false);
                    }
                    break;
                default:
                    break;
            }

            return super.onInterceptTouchEvent(event);
        }
}

3
投票

如果有人想要 kotlin 语言的课程。
我按照@rotem

的建议使用了
dispatchTouchEvent

class CustomMapView : MapView {
           constructor(context: Context):
            super(context)
    constructor(context: Context, googleMapOptions: GoogleMapOptions):
            super(context, googleMapOptions)
    constructor(context: Context, attributeSet: AttributeSet):
            super(context, attributeSet)
    constructor(context: Context, attributeSet: AttributeSet, int: Int):
            super(context, attributeSet, int)

    override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
        Log.d("CustomWebView", "touchevent")
        when(event?.action) {
            MotionEvent.ACTION_UP -> {
                Log.d("CustomWebView", "disallow Intercept")
                parent.requestDisallowInterceptTouchEvent(false)
            }
            MotionEvent.ACTION_DOWN -> {
                Log.d("CustomWebView", "allow Intercept")
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        return super.dispatchTouchEvent(event)
    }
}

2
投票

您可以简单地将 MapView 放入布局本身并覆盖 onTouch 或设置 Click-Listener - 对我来说最简单的方法,因为我需要触摸 ScrollView 中的整个 MapView。


1
投票

如果您在滚动视图中有地图视图,那么您必须向地图视图明确提及以下参数:

mMapView.setClickable(true);
mMapView.setFocusable(true);
mMapView.setDuplicateParentStateEnabled(false);

0
投票

在 Kotlin 中扩展 Mapbox 的 MapView(同时遵循 @fupduck 的代码):

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import com.mapbox.maps.MapInitOptions
import com.mapbox.maps.MapView

class CustomMapView : MapView {
    constructor(context: Context):
            super(context)
    constructor(context: Context, googleMapOptions: MapInitOptions):
            super(context, googleMapOptions)
    constructor(context: Context, attributeSet: AttributeSet):
            super(context, attributeSet)
    constructor(context: Context, attributeSet: AttributeSet, int: Int):
            super(context, attributeSet, int)

    override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
        Log.d("CustomWebView", "touchevent")
        when(event?.action) {
            MotionEvent.ACTION_UP -> {
                Log.d("CustomWebView", "disallow Intercept")
                parent.requestDisallowInterceptTouchEvent(false)
            }
            MotionEvent.ACTION_DOWN -> {
                Log.d("CustomWebView", "allow Intercept")
                parent.requestDisallowInterceptTouchEvent(true)
            }
        }
        return super.dispatchTouchEvent(event)
    }
}

可以在 XML 中轻松使用:

    <com.example.PackageName.CustomMapView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:mapbox="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/custom_map_view_route"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        mapbox:mapbox_cameraTargetLat="26"
        mapbox:mapbox_cameraTargetLng="75"
        mapbox:mapbox_cameraZoom="14.0" />
© www.soinside.com 2019 - 2024. All rights reserved.