Android Google Maps V2 - 禁止拖动或缩放滚动

9
我想要在Android的Google Maps中禁用滚动功能,只允许用户进行缩放操作。在iOS的Google Maps中,这很容易实现,只需设置一个参数:self.settings.allowScrollGesturesDuringRotateOrZoom = NO; 然而,我没能找到类似的功能在Android上实现的方法,所以正在寻求解决方案。目前我拥有的最好的想法是扩展Google Maps视图,拦截视图上的触摸事件,在捏合时手动设置缩放。但我认为这种方法不够正规且不可靠。是否有更好的方法?你有没有其他建议或想法?我还没有任何相关代码,无法在此处提供。此操作的背景是地图中心点有一个固定的标记,该中心点经纬度用于地址编码。

1
请给这个功能请求点赞,让谷歌知道我们需要它: https://issuetracker.google.com/issues/69795937 - dan
https://developers.google.com/android/reference/com/google/android/gms/maps/UiSettings.html#isScrollGesturesEnabledDuringRotateOrZoom() - Shahab Rauf
3个回答

7

编辑

现在有一种官方的方法来解决这个问题,已经被标记为正确答案。

旧回答

我最终采用了完全自定义的解决方案,尽管由于ScaleGestureDetector的错误,它只适用于API > 16。如果我找到解决方法,将会发布更新。目前,在API <= 16上启用缩放手势的是常规的Mapview,在API > 16上我使用我的自定义类:

    public class CustomEventMapView extends MapView {

    private int fingers = 0;
    private GoogleMap googleMap;
    private long lastZoomTime = 0;
    private float lastSpan = -1;
    private Handler handler = new Handler();

    private ScaleGestureDetector gestureDetector;

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

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

    @Override
    public void getMapAsync(final OnMapReadyCallback callback) {
        super.getMapAsync(new OnMapReadyCallback() {
            @Override
            public void onMapReady(final GoogleMap googleMap) {
                gestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
                    @Override
                    public boolean onScale(ScaleGestureDetector detector) {
                        if (lastSpan == -1) {
                            lastSpan = detector.getCurrentSpan();
                        } else if (detector.getEventTime() - lastZoomTime >= 50) {
                            lastZoomTime = detector.getEventTime();
                            googleMap.animateCamera(CameraUpdateFactory.zoomBy(getZoomValue(detector.getCurrentSpan(), lastSpan)), 50, null);
                            lastSpan = detector.getCurrentSpan();
                        }
                        return false;
                    }

                    @Override
                    public boolean onScaleBegin(ScaleGestureDetector detector) {
                        lastSpan = -1;
                        return true;
                    }

                    @Override
                    public void onScaleEnd(ScaleGestureDetector detector) {
                        lastSpan = -1;

                    }
                });
                CustomEventMapView.this.googleMap = googleMap;
                callback.onMapReady(googleMap);
            }
        });
    }

    private float getZoomValue(float currentSpan, float lastSpan) {
        double value = (Math.log(currentSpan / lastSpan) / Math.log(1.55d));
        return (float) value;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_POINTER_DOWN:
                fingers = fingers + 1;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                fingers = fingers - 1;
                break;
            case MotionEvent.ACTION_UP:
                fingers = 0;
                break;
            case MotionEvent.ACTION_DOWN:
                fingers = 1;
                break;
        }
        if (fingers > 1) {
            disableScrolling();
        } else if (fingers < 1) {
            enableScrolling();
        }
        if (fingers > 1) {
            return gestureDetector.onTouchEvent(ev);
        } else {
            return super.dispatchTouchEvent(ev);
        }
    }

    private void enableScrolling() {
        if (googleMap != null && !googleMap.getUiSettings().isScrollGesturesEnabled()) {
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    googleMap.getUiSettings().setAllGesturesEnabled(true);
                }
            }, 50);
        }
    }

    private void disableScrolling() {
        handler.removeCallbacksAndMessages(null);
        if (googleMap != null && googleMap.getUiSettings().isScrollGesturesEnabled()) {
            googleMap.getUiSettings().setAllGesturesEnabled(false);
        }
    }
}

3
Math.log(1.55d)的意思是以自然对数为底,以1.55为真数进行对数运算。而 (Math.log(currentSpan / lastSpan) / Math.log(1.55d))中的所有缩放计算使用的是以1.55为真数的对数,并将当前跨度与上一个跨度相除后得到结果。 - nostra13
当用户用两个手指不断触摸地图时,将连续调用disableScrolling()方法。如何阻止它的调用?因为这会导致相机空闲监听器被调用。但是,我需要在相机空闲监听器中执行一些操作。由于不断调用disableScrolling方法,相机空闲监听器中的操作会多次发生。 - Madhan

5

这是一个旧问题,但我遇到了相同的问题。通过一些搜索,我找到了这个解决方案(我认为这是正确的方法): 让您的活动实现onMapReadyCallback,然后在覆盖的onMapReady中设置googleMap.getUiSettings().setScrollGesturesEnabledDuringRotateOrZoom(false); 这对我有用。

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener{
        GoogleMap gMap;
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        gMap = googleMap;
        gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        gMap.getUiSettings().setZoomControlsEnabled(true);
        gMap.getUiSettings().setZoomGesturesEnabled(true);
        gMap.getUiSettings().setCompassEnabled(false);
        gMap.getUiSettings().setScrollGesturesEnabled(false);
        gMap.getUiSettings().setScrollGesturesEnabledDuringRotateOrZoom(false);
        gMap.setMyLocationEnabled(false);
        gMap.animateCamera(CameraUpdateFactory.zoomTo(8f));
    }

对我不起作用! - Akash Dubey

-2

我想允许滚动和缩放,但是我想在缩放期间禁止滚动。这将完全禁用滚动和缩放手势。 - splangi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接