如何使相机居中,使标记位于屏幕底部? (Google Map API V2 Android)

单击标记时,摄像机的默认行为是将其居中显示在屏幕中央,但是由于我通常在信息窗口中有较长的文字说明,因此实际更改摄像机位置更加方便,因为标记位于底部 屏幕(将信息窗口置于屏幕中央)。 我认为我应该能够通过覆盖如下所示的onMarkerClick函数来做到这一点(当此函数返回true时,默认行为将被取消)

@Override

public boolean onMarkerClick(final Marker marker) {


    // Google sample code comment : We return false to indicate that we have not

    // consumed the event and that we wish
    // for the default behavior to occur (which is for the camera to move
    // such that the
    // marker is centered and for the marker's info window to open, if it
    // has one).

    marker.showInfoWindow();

            CameraUpdate center=
                CameraUpdateFactory.newLatLng(new LatLng(XXXX,
                                                         XXXX));
            mMap.moveCamera(center);//my question is how to get this center

            // return false;
    return true;
}

编辑:

使用接受的答案步骤解决了问题,代码如下:

@Override

    public boolean onMarkerClick(final Marker marker) {

                //get the map container height
        LinearLayout mapContainer = (LinearLayout) findViewById(R.id.map_container);
        container_height = mapContainer.getHeight();

        Projection projection = mMap.getProjection();

        LatLng markerLatLng = new LatLng(marker.getPosition().latitude,
                marker.getPosition().longitude);
        Point markerScreenPosition = projection.toScreenLocation(markerLatLng);
        Point pointHalfScreenAbove = new Point(markerScreenPosition.x,
                markerScreenPosition.y - (container_height / 2));

        LatLng aboveMarkerLatLng = projection
                .fromScreenLocation(pointHalfScreenAbove);

        marker.showInfoWindow();
        CameraUpdate center = CameraUpdateFactory.newLatLng(aboveMarkerLatLng);
        mMap.moveCamera(center);
        return true;



    }

感谢您的帮助^ ^

Arch1tect asked 2020-08-01T11:41:25Z
9个解决方案
48 votes

我可能稍后会编辑此答案以提供一些代码,但是我认为可行的是:

  1. 获得LatLng(LatLng M)的点击标记。
  2. 使用LatLng方法将LatLng M转换为LatLng(点M)。 这使您可以在设备的显示屏上标记的位置(以像素为单位)。
  3. 计算一个点(新点)的位置,该点比M点高出地图高度的一半。
  4. 将新点转换回LatLng并在其上将地图居中。

在这里寻找有关如何获取地图高度的答案。

    // googleMap is a GoogleMap object
    // view is a View object containing the inflated map
    // marker is a Marker object
    Projection projection = googleMap.getProjection();
    LatLng markerPosition = marker.getPosition();
    Point markerPoint = projection.toScreenLocation(markerPosition);
    Point targetPoint = new Point(markerPoint.x, markerPoint.y - view.getHeight() / 2);
    LatLng targetPosition = projection.fromScreenLocation(targetPoint);
    googleMap.animateCamera(CameraUpdateFactory.newLatLng(targetPosition), 1000, null);
zbr answered 2020-08-01T11:41:57Z
20 votes

是的,使用Projection类。 进一步来说:

获取地图投影:

 Projection projection = map.getProjection();

获取标记的位置:

 LatLng markerLocation = marker.getPosition();

将位置传递给Projection.toScreenLocation()方法:

 Point screenPosition = projection.toScreenLocation(markerLocation);

这样,您可以相对于屏幕中心或围绕屏幕移动标记

Point mappoint = googleMap.getProjection().toScreenLocation(new LatLng(latitude, longitude));
        mappoint.set(mappoint.x, mappoint.y-30);
        googleMap.animateCamera(CameraUpdateFactory.newLatLng(googleMap.getProjection().fromScreenLocation(mappoint)));
Sampath Kumar answered 2020-08-01T11:42:34Z
7 votes

我更喜欢拉里·麦肯齐(Larry McKenzie)的答案,它不依赖于屏幕投影(即mProjection.toScreenLocation()),我的猜测是,当地图缩放级别较低时,投影分辨率会变差,这使我有时无法获得准确的图像。 位置。 因此,基于google map spec的计算肯定会解决该问题。

下面是将标记从底部移至屏幕大小的30%的示例代码。

zoom_lvl = mMap.getCameraPosition().zoom;
double dpPerdegree = 256.0*Math.pow(2, zoom_lvl)/170.0;
double screen_height = (double) mapContainer.getHeight();
double screen_height_30p = 30.0*screen_height/100.0;
double degree_30p = screen_height_30p/dpPerdegree;      
LatLng centerlatlng = new LatLng( latlng.latitude + degree_30p, latlng.longitude );         
mMap.animateCamera( CameraUpdateFactory.newLatLngZoom( centerlatlng, 15 ), 1000, null);
chunyap answered 2020-08-01T11:42:59Z
3 votes

我遇到了同样的问题,我尝试了以下完美的解决方案

mMap.setOnMarkerClickListener(new OnMarkerClickListener() 
        {
            @Override
            public boolean onMarkerClick(Marker marker)
            {
                int yMatrix = 200, xMatrix =40;

                DisplayMetrics metrics1 = new DisplayMetrics();
                getWindowManager().getDefaultDisplay().getMetrics(metrics1);
                switch(metrics1.densityDpi)
                {
                case DisplayMetrics.DENSITY_LOW:
                    yMatrix = 80;
                    xMatrix = 20;
                    break;
                case DisplayMetrics.DENSITY_MEDIUM:
                    yMatrix = 100;
                    xMatrix = 25;
                    break;
                case DisplayMetrics.DENSITY_HIGH:
                    yMatrix = 150;
                    xMatrix = 30;
                    break;
                case DisplayMetrics.DENSITY_XHIGH:
                    yMatrix = 200;
                    xMatrix = 40;
                    break;
                case DisplayMetrics.DENSITY_XXHIGH:
                    yMatrix = 200;
                    xMatrix = 50;
                    break;
                }

                Projection projection = mMap.getProjection();
                LatLng latLng = marker.getPosition();
                Point point = projection.toScreenLocation(latLng);
                Point point2 = new Point(point.x+xMatrix,point.y-yMatrix);

                LatLng point3 = projection.fromScreenLocation(point2);
                CameraUpdate zoom1 = CameraUpdateFactory.newLatLng(point3);
                mMap.animateCamera(zoom1);
                marker.showInfoWindow();
                return true;
            }
        });
Samadhan Medge answered 2020-08-01T11:43:19Z
3 votes

如果您不关心地图放大,只希望标记位于底部,请参见下面,我认为这是一个更简单的解决方案

double center = mMap.getCameraPosition().target.latitude;
double southMap = mMap.getProjection().getVisibleRegion().latLngBounds.southwest.latitude;

double diff = (center - southMap);

double newLat = marker.getPosition().latitude + diff;

CameraUpdate centerCam = CameraUpdateFactory.newLatLng(new LatLng(newLat, marker.getPosition().longitude));

mMap.animateCamera(centerCam);
Cam Connor answered 2020-08-01T11:43:39Z
1 votes

我做了一些研究,根据文档,地图是正方形的,在零缩放级别下,宽度和高度为256dp和+/- 85度N / S。 地图宽度随缩放级别而增加,因此宽度和高度= 256 * 2N dp。 其中N是缩放级别。 因此,从理论上讲,您可以通过获取地图高度并将其除以170总度数来确定新位置,从而获得每度dp。 然后获得以dp为单位的屏幕高度(或mapview高度)除以2,然后将一半视图尺寸转换为纬度。 然后将新的“相机”点设置为向南许多纬度。 如果您需要,我可以添加代码,但目前我正在打电话。

Larry McKenzie answered 2020-08-01T11:44:01Z
0 votes

我一直在尝试这里提出的所有解决方案,并结合了它们的实现。 考虑到地图的投影,倾斜,缩放和信息窗口的高度。

它并没有真正将标记放置在“相机视图”的底部,但是我认为在大多数情况下,它可以很好地容纳信息窗口和标记中心。

@Override
public boolean onMarkerClick(Marker marker) {
    mIsMarkerClick = true;
    mHandler.removeCallbacks(mUpdateTimeTask);
    mLoadTask.cancel(true);
    getActivity().setProgressBarIndeterminateVisibility(false);
    marker.showInfoWindow();
    Projection projection = getMap().getProjection();
    Point marketCenter = projection.toScreenLocation(marker.getPosition());
    float tiltFactor = (90 - getMap().getCameraPosition().tilt) / 90;
    marketCenter.y -= mInfoWindowAdapter.getInfoWindowHeight() / 2 * tiltFactor;
    LatLng fixLatLng = projection.fromScreenLocation(marketCenter);

    mMap.animateCamera(CameraUpdateFactory.newLatLng(fixLatLng), null);

    return true;
}

然后,您的自定义适配器将必须保留信息窗口实例的展开视图,以便能够获取其高度。

public int getInfoWindowHeight(){
    if (mLastInfoWindoView != null){
        return mLastInfoWindoView.getMeasuredHeight();
    }
    return 0;
}
mdelolmo answered 2020-08-01T11:44:30Z
0 votes

仍在寻找根据位置坐标将相机居中的任何人

CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(Lat, Lon))
        .zoom(15) 
        .bearing(0)
        .tilt(45)
        .build();
    map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

学分

user3354265 answered 2020-08-01T11:44:54Z
0 votes

经过一些经验,我已经实施了适合我的解决方案。

DisplayMetrics metrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(metrics);

Point targetPoint = new Point(metrics.widthPixels / 2, metrics.heightPixels - metrics.heightPixels / 9);
LatLng targetLatlng = map.getProjection().fromScreenLocation(targetPoint);
double fromCenterToTarget = SphericalUtil.computeDistanceBetween(map.getCameraPosition().target, targetLatlng);

LatLng center = SphericalUtil.computeOffset(new LatLng(location.latitude, location.longitude), fromCenterToTarget/1.2, location.bearing);
CameraUpdate camera = CameraUpdateFactory.newLatLng(center);
map.animateCamera(camera, 1000, null);

这里。 首先,我们在屏幕上选择应该移动标记的物理点。 然后,将其转换为LatLng。 下一步-计算从当前标记位置(在中心)到目标的距离。 最后,我们将地图中心从标记笔直移动到计算出的距离。

Edward answered 2020-08-01T11:45:19Z
translate from https://stackoverflow.com:/questions/16764002/how-to-center-the-camera-so-that-marker-is-at-the-bottom-of-screen-google-map