通过包装器中心缩放Google Map?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过包装器中心缩放Google Map?相关的知识,希望对你有一定的参考价值。

如何在地图上方的透明ImageView上设置侦听器,仅对其上的捏合(缩放)事件作出反应,而其他所有内容如移动地图都由Google地图处理?

我的目标是在地图上创建中心缩放,可以这样做:

 mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mGoogleMap.getCameraPosition().target, amountOfZoomNeeded));

但是我需要首先捕获那个捏合事件,并且只有那个事件因为onTouch阻止使用下面的地图。

编辑:

我设法使用ScaleGestureDetectors onScale()方法创建居中缩放:

public class PinchListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    private GoogleMap googleMap;

    public PinchListener(GoogleMap googleMap){
        this.googleMap = googleMap;
    }


    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        double zoom = googleMap.getCameraPosition().zoom;
        zoom = zoom + Math.log(detector.getScaleFactor()) / Math.log(1.5d);
        CameraUpdate update =  CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, (float) zoom);

        googleMap.moveCamera(update);
        return true;
    }
}

在我的MainActivity中我初始化它,其中mMapWrapper是我前面提到的透明ImageView包装器。

ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(this, new PinchListener(mGoogleMap));

mMapWrapper.setOnTouchListener(new View.OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        mScaleGestureDetector.onTouchEvent(event);
        return true;
    }
});

但是现在我遇到了一个无法移动地图的问题,因为所有触摸事件都被包装器的onTouch()方法吃掉了。我怎样才能防止这种情况发生?

答案

所以这就是我设法做到这一点的方式。

我创建了两个用于检测某些事件的类,如fling,double tap,scroll(drag)和scale(zoom):

public class PinchListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    private GoogleMap mGoogleMap;

    public PinchListener(GoogleMap googleMap) {
        this.mGoogleMap = googleMap;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        double zoom = mGoogleMap.getCameraPosition().zoom;
        zoom = zoom + Math.log(detector.getScaleFactor()) / Math.log(1.5d);
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(mGoogleMap.getCameraPosition().target, (float) zoom);
        mGoogleMap.moveCamera(update);
        return true;
    }
}

public class GestureListener extends GestureDetector.SimpleOnGestureListener {

    private GoogleMap mGoogleMap;
    private boolean mIsInAnimation;

    public GestureListener(GoogleMap googleMap) {
        this.mGoogleMap = googleMap;
        mIsInAnimation = false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        LatLng target = mGoogleMap.getCameraPosition().target;
        Point screenPoint = mGoogleMap.getProjection().toScreenLocation(target);
        Point newPoint = new Point(screenPoint.x + (int) distanceX, screenPoint.y + (int) distanceY);
        LatLng mapNewTarget = mGoogleMap.getProjection().fromScreenLocation(newPoint);

        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(
                mapNewTarget, mGoogleMap.getCameraPosition().zoom);
        mGoogleMap.moveCamera(update);
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        mGoogleMap.animateCamera(CameraUpdateFactory.zoomIn(), 400, null);
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (mIsInAnimation) return false;
        int velocity = (int) Math.sqrt(velocityX * velocityX + velocityY * velocityY);
        if (velocity < 500) return false;
        double k1 = 0.002d; /*exipemental*/
        double k2 = 0.002d;/*exipemental*/

        LatLng target = mGoogleMap.getCameraPosition().target;
        Point screenPoint = mGoogleMap.getProjection().toScreenLocation(target);

        Point newPoint = new Point(screenPoint.x - (int) (velocityX * k1),
                screenPoint.y - (int) (velocityY * k1));
        LatLng mapNewTarget = mGoogleMap.getProjection().fromScreenLocation(newPoint);

        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(
                mapNewTarget, mGoogleMap.getCameraPosition().zoom);

        tryUpdateCamera(update, (int) (velocity * k2));
        return true;
    }

    private void tryUpdateCamera(CameraUpdate update, int animateTime) {
        mIsInAnimation = true;
        mGoogleMap.animateCamera(update, animateTime, new GoogleMap.CancelableCallback() {
            @Override
            public void onFinish() {
                mIsInAnimation = false;
            }

            @Override
            public void onCancel() {
                mIsInAnimation = false;
            }
        });
    }
}

然后我在MainActivity中初始化了一个GestureDetector和ScaleGestureDetector:

ScaleGestureDetector mScaleGestureDetector = new ScaleGestureDetector(this, new PinchListener(mMap));
GestureDetector mGestureDetector = new GestureDetector(this, new GestureListener(mMap));

我已经在我的activity_main中创建了一个透明的图像包装器来检测所有这些事件,然后在下面的Google Map上模拟它们,如下所示:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:id="@+id/map"/>

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mapWrapper"
/>

最后在我的MainActivity中,我为包装器创建了一个OnTouchListener:

mMapWrapper = findViewById(R.id.mapWrapper);

mMapWrapper.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction() & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    mMode = Mode.DRAG;
                    mGestureDetector.onTouchEvent(event);
                    mScaleGestureDetector.onTouchEvent(event);
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    mMode = Mode.ZOOM;
                    mScaleGestureDetector.onTouchEvent(event);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_POINTER_UP:
                    mMode = Mode.NONE;
                    mGestureDetector.onTouchEvent(event);
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mMode == Mode.DRAG) {
                        mGestureDetector.onTouchEvent(event);
                    } else if (mMode == Mode.ZOOM) {
                        mScaleGestureDetector.onTouchEvent(event);
                    }
                    break;
            }

            return true;
        }
    });

在最后一步中,我向正确的探测器“提供”我想要的事件。如果我没有这样做,缩放将不会完全居中,因为有时会调用滚动(拖动)事件并且会移动地图。

以上是关于通过包装器中心缩放Google Map?的主要内容,如果未能解决你的问题,请参考以下文章

从 Bokeh Google Maps 包装器 (fitBounds()) 调用 Javascript 方法

css 快速片段将svg与中心对齐并缩放到视口大小。

为两个 LatLong 值计算 Google Map 的缩放级别

php 一个自定义的try..catch包装器代码片段,用于执行模型函数,使其成为一个单行函数调用

为移动目标 lat/lng 和缩放级别的动画偏移地图片段的中心

如何为 google map api v2 设置默认位置和缩放级别?