【问题标题】:zoom over specific route google map放大特定路线谷歌地图
【发布时间】:2017-02-01 02:04:14
【问题描述】:

我有一个随机纬度和经度点的列表,我正在它们之间绘制一条路线。我的问题是如何在我在实用方法下面制作的谷歌地图中绑定这条路线

public static void drawRouteIntoMap(final List<? extends MapHelper> position, final GoogleMap googleMap) {
    /*List<MapHelper> position = new ArrayList<MapHelper>();
    for (int i = lastPosition; i < maps.size(); i++) {
        position.add(maps.get(i));
    }*/
    if (position.size() > 0 && Validator.isNotNull(googleMap)) {
        googleMap.clear();
        List<PolylineOptions> polylineOptionses = new ArrayList<PolylineOptions>();
        PolylineOptions option = null;
        Boolean lastPause = null;
        for (MapHelper map : position) {
            if (map.isPause()) {
                if (Validator.isNull(lastPause) || !lastPause) {
                    option = new PolylineOptions().width(5).color(Color.rgb(255, 0, 155)).geodesic(true);
                    polylineOptionses.add(option);
                }
                option.add(new LatLng(map.getLatitude(), map.getLongitude()));
            } else {
                if (Validator.isNull(lastPause) || lastPause) {
                    option = new PolylineOptions().width(5).color(Color.rgb(0, 179, 253)).geodesic(true);
                    polylineOptionses.add(option);
                }
                option.add(new LatLng(map.getLatitude(), map.getLongitude()));
            }
            lastPause = map.isPause();
        }
        for (PolylineOptions options : polylineOptionses) {
            googleMap.addPolyline(options);
        }
        if(Validator.isNotNull(option)){
            //List<LatLng> points = option.getPoints();
            final LatLngBounds.Builder mapBounds = new LatLngBounds.Builder();

            googleMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
                @Override
                public void onMapLoaded() {
                    LatLng startPoint = new LatLng(position.get(0).getLatitude(), position.get(0).getLongitude());
                    googleMap.addMarker(new MarkerOptions().position(startPoint).title("start").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
                    mapBounds.include(startPoint);
                    LatLng endPoint = new LatLng(position.get(position.size() - 1).getLatitude(), position.get(position.size() - 1).getLongitude());
                    mapBounds.include(endPoint);
                    googleMap.addMarker(new MarkerOptions().position(endPoint).title("finish").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
                    googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
                   /* googleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
                    googleMap.moveCamera(CameraUpdateFactory.zoomOut());*/

                }
            });
        }

    }
}

这里last pause是布尔值,表示是否为红色折线的暂停点。

但它不起作用。感谢任何帮助。

【问题讨论】:

  • @Yvette 我想在给定的地图视图中以精简模式显示整条路线,以便在这两个标记之间的起点、终点和折线清楚地看到整条路线
  • @Yvette 我已经上传了屏幕截图,有这些项目的列表
  • @Yvette 是的,我想在这个地图区域内显示这条不同的路线
  • 显示添加到地图的所有点。 stackoverflow.com/questions/19671790/…

标签: android google-maps-android-api-2 marker polyline


【解决方案1】:

尝试以这种方式实现

/**
 * Zooms a Route (given a List of LalLng) at the greatest possible zoom level.
 *
 * @param googleMap: instance of GoogleMap
 * @param lstLatLngRoute: list of LatLng forming Route
 */
public void zoomRoute(GoogleMap googleMap, List<LatLng> lstLatLngRoute) {

    if (googleMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return;

    LatLngBounds.Builder boundsBuilder = new LatLngBounds.Builder();
    for (LatLng latLngPoint : lstLatLngRoute)
        boundsBuilder.include(latLngPoint);

    int routePadding = 100;
    LatLngBounds latLngBounds = boundsBuilder.build();

    googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, routePadding));
}

更新

查看图片后,地图上方有布局。所以它需要你设置Variable Padding。你可以这样做

googleMap.setPadding(left, top, right, bottom);

注意:设置变量填充时,可以初始化routePadding = 0; 在您的情况下,近似值是:left = right = 10bottom=100top=200。设置完成后,您可以根据自己的要求进行校准。

Recommendation: You can calculate the height of those (top and bottom) layouts in pixels and then set padding accordingly.

【讨论】:

  • 为什么选择填充值 100?
  • 使用填充以便标记(如果存在于点)在缩放期间不会被剪裁,并且路线不会接触地图边缘。您可以设置自己的自定义值(例如,标记图像的高度或宽度)。如果您希望路线接触地图边缘,它甚至可以为 0。
  • 我已经尝试过您的解决方案,但仍有一些路线标记被剪裁,我可以上传屏幕截图
  • 尝试增加 Padding >= 2 * 标记高度(以像素为单位)
  • 目前我正在使用 BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED) 这个方法做标记
【解决方案2】:

放大不起作用的原因可能是在调用方法时地图尚未膨胀:

moveCamera(com.google.android.gms.maps.CameraUpdate)

尝试将ViewTreeObserver.OnGlobalLayoutListener 添加到地图中:

ViewTreeObserver vto = googleMap.getViewTreeObserver();
ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            googleMap.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        } else {
            googleMap.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
    }
};
vto.addOnGlobalLayoutListener(globalLayoutListener);

如果上面的方法不起作用GoogleMap有它自己的布局监听器,你可以使用它:

googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition arg0) {
        googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
        googleMap.setOnCameraChangeListener(null);
    }
});

但是,从 API 的 play-services-maps 9.4.0 版本开始,不推荐使用上述方法。使用以下之一:

【讨论】:

    【解决方案3】:

    您需要将构成折线的所有点包含到您的mapBounds 对象中。

    另外,您正在使用animateCamera 更新相机,然后您正在使用moveCamera 移动它。这第二个相机更新会覆盖第一个。只需删除该行

    googleMap.moveCamera(CameraUpdateFactory.zoomOut());
    

    这条线也是不必要的(你不需要移动和动画相机,只需其中之一):

    googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));
    

    如果您需要将地图缩小一点,您可以使用CameraUpdateFactory.newLatLngBounds 方法的填充参数。

    【讨论】:

    • 我已经上传了屏幕截图,看到标记没有正确显示这只是一条路线,可能还有其他类似的路线
    • 你的路线是怎么画的?可以举个例子吗?
    • 请检查我上传的方法
    • 您需要将构成折线的所有点添加到您的mapBounds
    • 看到我上传的图片在这个我已经包含了mapbounds中的所有点形成折线。仍然看不到结束标记
    【解决方案4】:

    我实现了一个与 @rishabh-dutt-sharma 类似的解决方案,但有一些变化:

    • 首先,在缩放之前检查点是否已经在视图内。如果是,请不要更改它。这意味着用户界面中不需要的更改会减少。
    • 其次,一种特殊情况是只有一个点。这在显示标记列表时很有用,在您的特定情况下可能不需要。之所以有用,是因为在单点的情况下,缩放通常会增加到最大,通常这太多了。

    这是代码(改编自我的原始代码,希望没有错别字):

        public void zoomRoute(GoogleMap googleMap, List<LatLng> lstLatLngRoute) {
    
            if (googleMap == null || lstLatLngRoute == null || lstLatLngRoute.isEmpty()) return;
    
            LatLngBounds currentLatLongBounds =
                    googleMap.getProjection().getVisibleRegion().latLngBounds;
            boolean updateBounds = false;
    
            for (LatLng latLng : lstLatLngRoute) {
                if (!currentLatLongBounds.contains(latLng)) {
                    updateBounds = true;
                }
            }
    
            if (updateBounds) {
    
                CameraUpdate cameraUpdate;
    
                if (lstLatLngRoute.size() == 1) {
    
                    LatLng latLng = lstLatLngRoute.iterator().next();
                    cameraUpdate = CameraUpdateFactory.newLatLng(latLng);
    
                } else {
    
                    LatLngBounds.Builder builder = LatLngBounds.builder();
                    for (LatLng latLng : lstLatLngRoute) {
                        builder.include(latLng);
                    }
                    LatLngBounds latLongBounds = builder.build();
    
                    cameraUpdate =
                            CameraUpdateFactory.newLatLngBounds(latLongBounds, MAP_ZOOM_PADDING);
    
                }
    
                try {
                    googleMap.animateCamera(cameraUpdate, MAP_CAMERA_ANIMATION_DURATION_IN_MILLIS,
                            new GoogleMap.CancelableCallback() {
                                @Override
                                public void onFinish() {
                                }
    
                                @Override
                                public void onCancel() {
                                }
                            });
                } catch (IllegalStateException ex) {
                    // Ignore it. We're just being a bit lazy, as this exception only happens if
                    // we try to animate the camera before the map has a size
                }
            }
        }
    

    【讨论】:

    • 填充和动画持续时间秒的这个常量的值是多少
    • Padding 是像素数,我使用 90dp 来实现密度无关性,您可以将其存储在 dimen 资源中或使用如下例程从常量转换:public static float dipToPixels(Context context, float dipValue) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics); }。动画持续时间以毫秒为单位,我使用 500 来获得快速流畅的动画。
    【解决方案5】:

    你可以做一件事,找出2个纬度和经度之间的距离,然后检查你得到的距离。看看它是如何工作的。 这是一个可能对你有用的技巧。

    googleMap.moveCamera(CameraUpdateFactory.newLatLng(reachLocationLatLng));
    if (dist > 2 && dist <= 5) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(13.0f));
    mapZoomLevel = 12;
    } else if (dist > 5 && dist <= 10) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(12.0f));
    mapZoomLevel = 11;
    } else if (dist > 10 && dist <= 20) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(11.0f));
    mapZoomLevel = 11;
    } else if (dist > 20 && dist <= 40) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(10.0f));
    mapZoomLevel = 10;
    } else if (dist > 40 && dist < 100) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(9.0f));
    mapZoomLevel = 9;
    } else if (dist > 100 && dist < 200) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(8.0f));
    mapZoomLevel = 8;
    } else if (dist > 200 && dist < 400) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(7.0f));
    mapZoomLevel = 7;
    } else if (dist > 400 && dist < 700) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(6.0f));
    mapZoomLevel = 7;
    } else if (dist > 700 && dist < 1000) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(5.0f));
    mapZoomLevel = 6;
    } else if (dist > 1000) {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(4.0f));
    mapZoomLevel = 5;
    } else {
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(14.0f));
    mapZoomLevel = 14;
    }
    

    谢谢,希望对你有帮助。

    【讨论】:

      【解决方案6】:
       googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(endPoint,zoomLevel));
      

      如果对你有帮助就试试

      【讨论】:

      • 我设置了什么缩放级别
      • 您可以尝试任何数字 10、12、15 并检查更改
      • 在所有这些行之后我添加这个或在任何其他地方?
      • googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapBounds.build(), 10));替换这一行
      • 您尝试了哪些值以及您可以看到的输出
      【解决方案7】:

      我是怎么做到的。

      Android - plotting gps coordinate on custom map

      是的,您可以绘制不在可见地图上的点。通过设置 LatLngBounds 来解决这个问题。然后显示 LatLngBounds 的地图。您还可以移动地图以显示 LatLngBounds。这里没有什么棘手的问题,没有切线、斜坡或地球的双曲线曲率。所有这些都以度为单位进行处理,因此不要过度考虑您的解决方案。如果你转动地图,点就会随之转动。因此,将您的点添加到地图上,找到边界并倾斜相机。将相机向后倾斜,所有点仍将在屏幕上!这将使您从屏幕上的所有点开始。

      与示例获取对谷歌地图的引用相同。

      private void setUpMapIfNeeded() {
      // Do a null check to confirm that we have not already instantiated the
      // map.
      
      if (mMap == null) {
          // Try to obtain the map from the SupportMapFragment.
          // mMap = mMapFragment.getMap();
          // // Check if we were successful in obtaining the map.
      
          // Try to obtain the map from the SupportMapFragment.
          mMap = ((SupportMapFragment) getSupportFragmentManager()
                  .findFragmentById(R.id.map)).getMap();
          // use the settings maptype
      
          // Check if we were successful in obtaining the map.
          if (mMap != null) {
              setUpMap();
          }
      }
      }
      

      让我们开始寻找地图的边界。

      import com.google.android.gms.maps.model.LatLng;
      import com.google.android.gms.maps.model.LatLngBounds;
      A field for LatLngBounds and a LatLngBounds.Builder
      
      private LatLngBounds bounds;
      private LatLngBounds.Builder myLatLngBuilder;
      initialize the LatLngBounds.Builder
      
      myLatLngBuilder = new LatLngBounds.Builder();
      for each point on your map.
      
      LatLng myLatLng = new LatLng(latitude, longitude);
      myLatLngBuilder.include(myLatLng);
      Then when your finished adding points build your boundary.
      
      bounds = myLatLngBuilder.build();
      Now I have the bounds of all the points on my map and I can display just that area of the map. This code I lifted from the map samples.
      
      final View mapView = getSupportFragmentManager().findFragmentById(
                  R.id.map).getView();
          if (mapView.getViewTreeObserver().isAlive()) {
              mapView.getViewTreeObserver().addOnGlobalLayoutListener(
                      new OnGlobalLayoutListener() {
                          @SuppressWarnings("deprecation")
                          // We use the new method when supported
                          @SuppressLint("NewApi")
                          // We check which build version we are using.
                          @Override
                          public void onGlobalLayout() {
                              if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                                  mapView.getViewTreeObserver()
                                          .removeGlobalOnLayoutListener(this);
                              } else {
                                  mapView.getViewTreeObserver()
                                          .removeOnGlobalLayoutListener(this);
                              }
                              mMap.moveCamera(CameraUpdateFactory
                                      .newLatLngBounds(bounds, 50));
                          }
                      });
          }
      

      【讨论】:

        【解决方案8】:

        这个回答太晚了 尝试这种最短的方式

        首先获取您当前的位置 latlongs,然后为您的目的地 lat longs 编写代码,然后使用此代码计算您当前位置和目的地位置之间的距离

        private double distance(double lat1, double lon1, double lat2, double lon2) {
          double theta = lon1 - lon2;
          double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
          dist = Math.acos(dist);
          dist = rad2deg(dist);
          dist = dist * 60 * 1.1515;
           return (dist);
        }
        private double deg2rad(double deg) {
          return (deg * Math.PI / 180.0);
        }
        private double rad2deg(double rad) {
          return (rad * 180.0 / Math.PI);
        }
        
        • 您永远无法获得相同的经纬度数据,因为距离您当前位置 95 米的 GPS 计数显示当前位置图钉或经度数据。 要么您在同一个位置,您永远无法找到确切的经纬度数据,这必须在点上有所不同,因此您需要将当前位置与固定经度数据点保持距离。

        • 当您发现“distance”从您的目的地点到当前纬度时,然后触发此代码以动画相机和缩放。

          map.moveCamera( CameraUpdateFactory.newLatLngZoom(new LatLng(xxxx,xxxx),21));
          

        【讨论】:

          【解决方案9】:

          这可能是上述问题最简单的解决方案,它对我来说非常有效。

          在 GoogleMapOptions:camera 下将所有航路点添加到目标,然后它会自动设置缩放并将地图相对于折线(给定路线)居中。

          loadMap() {
          
          let mapOptions: GoogleMapOptions = {
            camera: {
              target: this.wayPoints,
              zoom: 25,
              tilt: 30
            }
          };
          
          this.map = GoogleMaps.create('map_canvas', mapOptions);
          this.map.one(GoogleMapsEvent.MAP_READY)
            .then(() => {
              console.log('Map is ready!');
          
          
             this.map.addPolyline({
                points:this.wayPoints,
                color:'#586bff',
                width: 8,
                geodesic:true,
              });
          });
          }
          

          航点(this.wayPoints)应采用以下格式:

          [{lat: 52.33806, lng: 8.61179},
          {lat: 52.33812, lng: 8.61185},
          {lat: 52.33812, lng: 8.61186},
          {lat: 52.33812, lng: 8.61188}]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-08-28
            • 2011-08-24
            • 2014-08-12
            • 2014-08-14
            • 2012-12-08
            • 2011-07-22
            • 2012-05-17
            相关资源
            最近更新 更多