如何使相机居中,使标记位于屏幕底部? (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; } 

感谢您的帮助^ ^

我可能稍后编辑这个答案来提供一些代码,但我认为可以工作的是这样的:

  1. 获取点击标记的LatLngLatLng M )。
  2. 使用Projection.toScreenLocation(LatLng)方法将LatLng M转换为PointPoint 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); 

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

获取地图投影:

  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))); 

我更喜欢拉里·麦肯齐的答案,它不依赖于屏幕投影(即mProjection.toScreenLocation()),我的猜测是当地图缩放级别低时,投影分辨率会变差,这使我有时无法获得准确位置。 所以,基于谷歌地图规范的计算必将解决问题。

以下是将标记从底部移动到屏幕大小的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); 

我有同样的问题,我尝试了以下完美的工作解决scheme

 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; } }); 

如果你不关心地图放大,只是想要标记在底部,我认为这是一个更简单的解决scheme

 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); 

我做了一点研究,根据文件的地图是正方形,在零缩放级别的宽度和高度是256dp和+/- 85度N / S。 地图宽度随着缩放级别增加,宽度和高度= 256 * 2N dp。 其中N是缩放级别。 所以理论上你可以通过获得地图高度来确定新的位置,并将其除以总共170度以获得每度的dp。 然后在dp中将屏幕高度(或mapview高度)除以2,并将半视图大小转换为纬度。 然后设置你的新的相机点,南纬度多。 我可以添加代码,如果你需要它,但我现在在手机上。

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

它不会真的把标记放在“相机视图”的底部,但是我认为在大多数情况下它可以很好地适应信息窗口和标记中心。

 @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; } 

任何仍在寻找根据位置坐标来定位相机的人

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

积分

经过一些经验,我已经实施了对我来说很好的解决scheme。

 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); 

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