无论您在 android 上的何处捏合缩放,都保持地图居中 [英] Keep map centered regardless of where you pinch zoom on android

查看:26
本文介绍了无论您在 android 上的何处捏合缩放,都保持地图居中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望做一些类似于 Uber 处理双指缩放事件的方式.无论您在屏幕上的哪个位置捏合,它都会使地图居中并放大中心位置.有没有办法在地图片段上没有某种覆盖的情况下做到这一点?或者我应该禁用地图的事件,在地图片段上创建一个叠加层,并处理叠加层中的所有缩放/其他事件?

I'm looking to do something similar to the way Uber handles pinch zoom events. No matter where you pinch on the screen, it keeps the map centered and zooms in on the center location. Is there a way to do this without having some sort of overlay over the map fragment? Or should I just disable maps' events, create an overlay over the map fragment, and handle all zoom / other events from the overlay?

推荐答案

我在google上搜索了大约3天,找到了完整的解决方案.我的回答来自 https://stackoverflow.com/a/32734436/3693334.

I've founded complete solution after spending about 3 days to search on google. My answer is edited from https://stackoverflow.com/a/32734436/3693334.

public class CustomMapView extends MapView {

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

    private ScaleGestureDetector scaleGestureDetector;
    private GestureDetector gestureDetector;

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

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

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

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

    public void init(GoogleMap map) {
        scaleGestureDetector = 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;

            }
        });
        gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
            @Override
            public boolean onDoubleTapEvent(MotionEvent e) {

                disableScrolling();
                googleMap.animateCamera(CameraUpdateFactory.zoomIn(), 400, null);

                return true;
            }
        });
        googleMap = map;
    }

    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) {
        gestureDetector.onTouchEvent(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 scaleGestureDetector.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);
        }
    }
}

并自定义 MapFragment

and customize MapFragment

public class CustomMapFragment extends Fragment {

        CustomMapView view;
        Bundle bundle;
        GoogleMap map;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            bundle = savedInstanceState;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.fragment_map, container, false);

            view = (CustomMapView) v.findViewById(R.id.mapView);
            view.onCreate(bundle);
            view.onResume();

            map = view.getMap();
            view.init(map);

            MapsInitializer.initialize(getActivity());

            return v;
        }

        public GoogleMap getMap() {
            return map;
        }

        @Override
        public void onResume() {
            super.onResume();
            view.onResume();
        }

        @Override
        public void onPause() {
            super.onPause();
            view.onPause();
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            view.onDestroy();
        }

        @Override
        public void onLowMemory() {
            super.onLowMemory();
            view.onLowMemory();
        }
    }

最后,在您的活动中:

....
<fragment
    android:id="@+id/map"
    class="yourpackage.CustomMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
...

我已经在 Android 4.1 (API 16) 及更高版本上进行了测试,它运行良好且流畅.(关于 API <16,我没有任何设备可以测试).

I've already tested on Android 4.1 (API 16) and latter, it work fine and smooth. (About API < 16, I haven't any device to test).

这篇关于无论您在 android 上的何处捏合缩放,都保持地图居中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆