Geo*_*off 5 android google-maps google-maps-markers google-maps-android-api-2
我已经通过谷歌地图路由添加了当前位置
Routing routing = new Routing.Builder()
.travelMode(Routing.TravelMode.DRIVING)
.key(getResources().getString(R.string.google_maps_api))
.withListener(this)
.waypoints(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()), site_location)
.alternativeRoutes(false)
.build();
routing.execute();
@Override
public void onRoutingSuccess(ArrayList<Route> route, int shortestRouteIndex) {
if (polylines.size() > 0) {
for (Polyline poly : polylines) {
poly.remove();
}
}
polylines = new ArrayList<>();
//add route(s) to the map.
for (int i = 0; i < route.size(); i++) {
//In case of more than 5 alternative routes
int colorIndex = i % COLORS.length;
PolylineOptions polyOptions = new PolylineOptions();
polyOptions.color(getResources().getColor(COLORS[colorIndex]));
polyOptions.width(10 + i * 13);
polyOptions.addAll(route.get(i).getPoints());
Polyline polyline = googleMap.addPolyline(polyOptions);
polylines.add(polyline);
int distance = route.get(i).getDistanceValue();
if (distance < 1000){
totalKm.setText( distance+" Metres");
}else {
totalKm.setText( (distance/1000) +" km");
}
}
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(new LatLng(mLastKnownLocation.getLatitude(), mLastKnownLocation.getLongitude()));
builder.include(site_marker.getPosition());
LatLngBounds bounds = builder.build();
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 100);
googleMap.animateCamera(cu);
}
Run Code Online (Sandbox Code Playgroud)
这会显示行车路线,例如
但是我正在尝试使用缩放视图显示默认的谷歌地图驾驶图标
我如何继续添加这样的地图,同时仍然保留折线以显示驾驶视图。
Jinesh Francis的回答完全正确:您应该通过意图运行默认地图Google Maps应用程序或修改标准MapView(或MapFragment)。
TLDR;
如果您选择第二种方式 - 最简单的方法是使用 Android Google Maps API 的标准类来创建您的示例中的视图(另一种方式是创建MapView基于自定义视图)。
首先仔细阅读第 3.2.4 页Google Maps Platform 服务条款对滥用服务的限制 (d) :
(d) 不得重新创建 Google 产品或功能。客户不得使用服务来创建产品或服务,其功能与其他 Google 产品或服务的功能基本相似或重新创建了其他 Google 产品或服务的功能。客户的产品或服务必须包含 Google 产品或服务之外的实质性、独立的价值和功能。例如,客户不得:(i) 重新分发 Google 地图核心服务或将其作为客户的服务进行分发;(ii) 创建谷歌地图核心服务、谷歌地图或谷歌地图移动应用程序或其功能的替代品;(iii) 在列表或目录服务中使用 Google 地图核心服务,或者创建或增强广告产品;(iv) 结合来自 Directions API、Geolocation API、
如果您不违反服务条款,您可以对这些步骤/任务做您想做的事情:
1) 获取用户当前位置;
2) 获取距离用户当前位置最近的路线路径段(因为用户位置很少正好在路上);
3) 获取该段的方位角(方位角);
4) 显示带有路线路径和用户当前位置标记的地图,并根据路径段方位进行适当的倾斜和旋转。
Run Code Online (Sandbox Code Playgroud)private final LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(final Location location) { //your code here } };
任务 2 可以通过PolyUtil.isLocationOnPath()像那个答案来解决:
Run Code Online (Sandbox Code Playgroud)private LatLng getMarkerProjectionOnSegment(LatLng carPos, List<LatLng> segment, Projection projection) { LatLng markerProjection = null; Point carPosOnScreen = projection.toScreenLocation(carPos); Point p1 = projection.toScreenLocation(segment.get(0)); Point p2 = projection.toScreenLocation(segment.get(1)); Point carPosOnSegment = new Point(); float denominator = (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y); // p1 and p2 are the same if (Math.abs(denominator) <= 1E-10) { markerProjection = segment.get(0); } else { float t = (carPosOnScreen.x * (p2.x - p1.x) - (p2.x - p1.x) * p1.x + carPosOnScreen.y * (p2.y - p1.y) - (p2.y - p1.y) * p1.y) / denominator; carPosOnSegment.x = (int) (p1.x + (p2.x - p1.x) * t); carPosOnSegment.y = (int) (p1.y + (p2.y - p1.y) * t); markerProjection = projection.fromScreenLocation(carPosOnSegment); } return markerProjection; }
任务 3 可以用这样的代码解决:
private float getBearing(LatLng begin, LatLng end) {
double dLon = (end.longitude - begin.longitude);
double x = Math.sin(Math.toRadians(dLon)) * Math.cos(Math.toRadians(end.latitude));
double y = Math.cos(Math.toRadians(begin.latitude))*Math.sin(Math.toRadians(end.latitude))
- Math.sin(Math.toRadians(begin.latitude))*Math.cos(Math.toRadians(end.latitude)) * Math.cos(Math.toRadians(dLon));
double bearing = Math.toDegrees((Math.atan2(x, y)));
return (float) bearing;
}
Run Code Online (Sandbox Code Playgroud)
其中begin和end是当前路线路径段的起点和终点。
任务 4 可以用这样的代码解决:
作为标记,您可以使用像这样的北向箭头的矢量可绘制:
ic_up_arrow_circle.xml (您也可以调整透明度和颜色):
<vector android:height="24dp" android:viewportHeight="93.934"
android:viewportWidth="93.934"
android:width="24dp"
xmlns:android="http://schemas.android.com/apk/res/android">
<path
android:fillColor="#8fFF0000"
android:pathData="m0,46.9666c0,25.939 21.028,46.967 46.967,46.967c25.939,-0 46.967,-21.028 46.967,-46.967c0,-25.939 -21.027,-46.967 -46.967,-46.967c-25.939,-0 -46.967,21.028 -46.967,46.967zM78.262,67.4396l-31.295,-16.845l-31.295,16.845l31.295,-51.614l31.295,51.614z"
/>
<path
android:fillColor="#FFFFFF"
android:pathData="M78.262,67.4396l-31.295,-16.845l-31.295,16.845l31.295,-51.614l31.295,51.614z"
/>
</vector>
Run Code Online (Sandbox Code Playgroud)
你可以用这样的代码把它放在地图上:
public Marker addDirectionMarker(LatLng latLng, float angle) {
Drawable circleDrawable = ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_up_arrow_in_circle);
BitmapDescriptor markerIcon = getMarkerIconFromDrawable(circleDrawable, 150, 150);
return mGoogleMap.addMarker(new MarkerOptions()
.position(latLng)
.anchor(0.5f, 0.5f)
.rotation(angle)
.flat(true)
.icon(markerIcon)
);
}
Run Code Online (Sandbox Code Playgroud)
哪里150是标记大小(以像素为单位)。注意!您需要flat标记以使其随地图旋转和倾斜,并0.5f准确地在其中心点移动标记锚点。
然后你可以在地图上显示所有这些:
...
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(userPosition)
.tilt(tilt)
.zoom(zoom)
.bearing(bearing)
.build();
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
...
Run Code Online (Sandbox Code Playgroud)
但是,如果您只在屏幕中心显示用户当前位置的标记(因为GoogleMap.moveCamera()将中心精确设置为.target())。因此,为了避免它,您需要稍微向下移动地图 - 在这种情况下,用户位置标记应出现在屏幕底部。对于地图中心偏移,您需要获取当前地图中心屏幕坐标,然后更改y坐标并获取新的屏幕中心。类似的东西:
...
LatLng mapCenter = mGoogleMap.getCameraPosition().target;
Projection projection = mGoogleMap.getProjection();
Point centerPoint = projection.toScreenLocation(mapCenter);
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int displayHeight = displayMetrics.heightPixels;
centerPoint.y = centerPoint.y - (int) (displayHeight / 4.5); // move center down for approx 22%
LatLng newCenterPoint = projection.fromScreenLocation(centerPoint);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(newCenterPoint, zoom));
...
Run Code Online (Sandbox Code Playgroud)
有了所有这些东西,对于您的路线(使用zoom= 15 和tilt = 50),您应该得到类似的东西:
如您所见,路线路径并不完全在路上,因此您需要比 Directions API 响应更精确地获取路线路径点。您可以通过Google Maps Roads API部分Snap to Road 获得它
为给定的 GPS 坐标集返回最适合的道路几何形状。该服务需要沿路线收集多达 100 个 GPS 点,并返回一组类似的数据,这些点被捕捉到车辆行驶的最有可能的道路上。
就像在那个答案中一样。如果您的路线路径有多个点,您需要分成 100 个点的部分并分别处理它们(Snap to Road API 也有每个用户(IP)每天 2500 个请求和每秒 10 个请求的限制)。
正如Jaswant Singh回答你的那样:
需要在当前位置设置自定义标记(图标与蓝色箭头相同),并在每次调用 onLocationChanged() 回调时将其移动到新位置(同时将相机动画到该新位置)。
此外,您需要根据当前用户速度进行选择zoom和tilt属性:当用户驾驶速度更快时tilt -> 0。等等。这不是一项简单的任务。
除了 Jinesh\xe2\x80\x99s 答案之外,\n如果您仍想添加该标记进行开发,您需要在当前位置设置一个自定义标记(图标与蓝色箭头相同)并将其移动到新位置每次调用 onLocationChanged() 回调时的位置(同时将相机动画设置到该新位置)。\n稍微倾斜地图以获得谷歌地图导航视图的精确外观,尽管您无法\xe2\x80\x99使用所有功能,但\xe2\x80\x99值得一试。
\n| 归档时间: |
|
| 查看次数: |
2927 次 |
| 最近记录: |