簡體   English   中英

在 Google 地圖上移動和顯示行車攝像頭視圖

[英]Moving and showing the driving camera view on Google maps

我已經通過谷歌 map 路由添加了當前位置

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

}

這顯示了一個行車路線,如

在此處輸入圖像描述

但我試圖用縮放視圖顯示默認的谷歌 map 駕駛圖標

在此處輸入圖像描述

我如何繼續添加這樣的 map,同時仍保留折線以顯示駕駛視圖。

Jinesh Francis的回答完全正確:您應該通過意圖運行默認的 map Google Maps 應用程序或修改標准MapView (或MapFragment )。

TLDR;

如果您選擇第二種方式 - 最簡單的方法是使用 Android Google Maps API 的標准類來創建您的示例中的視圖(其他方式是創建基於MapView的自定義視圖)。

首先仔細閱讀Google Maps Platform 服務條款第 3.2.4 條禁止濫用服務的限制 (d):

(d) 不得重新創建 Google 產品或功能。 客戶不得使用服務創建具有與其他 Google 產品或服務的功能大體相似或重新創建的其他 Google 產品或服務的功能的產品或服務。 客戶的產品或服務必須包含 Google 產品或服務之外的大量獨立價值和功能。 例如,客戶不得:(i) 重新分發 Google 地圖核心服務或將其作為客戶的服務進行傳遞; (ii) 創建谷歌地圖核心服務、谷歌地圖或谷歌地圖移動應用程序或其功能的替代品; (iii) 在列表或目錄服務中使用 Google 地圖核心服務,或者創建或擴充廣告產品; (iv) combine data from the Directions API, Geolocation API, and Maps SDK for Android to create real-time navigation functionality substantially similar to the functionality provided by the Google Maps for Android mobile app.

如果您不違反服務條款,您可以使用這些步驟/任務做您想做的事情:

1) 獲取用戶當前位置;

2) 獲得最接近用戶當前位置的路線路徑段(因為用戶位置很少正好在路上);

3)得到這個段的方位角(方位角);

4) 顯示帶有路徑路徑的 map 和用戶當前 position 標記,並根據路徑段方位進行適當的傾斜和旋轉。

任務 1 可以像Axxiss這個答案一樣解決:

 private final LocationListener mLocationListener = new LocationListener() { @Override public void onLocationChanged(final Location location) { //your code here } };

任務 2 可以通過PolyUtil.isLocationOnPath()解決,就像在那個答案中一樣:

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

其中beginend是當前路線路徑段的開始和結束。

任務 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>

你可以把它放在 map 上,代碼如下:

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

其中150是以像素為單位的標記大小。 注意! 您需要flat標記以使其旋轉和傾斜 map 和0.5f以將標記錨點精確地移動到其中心點。

然后你可以在 map 上顯示所有這些:

...
CameraPosition cameraPosition = new CameraPosition.Builder()
        .target(userPosition)
        .tilt(tilt)
        .zoom(zoom)
        .bearing(bearing)
        .build();
mGoogleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
...

但是,如果您只做用戶當前 position 的那個標記出現在屏幕的中心(因為GoogleMap.moveCamera()將中心正好設置在.target() )。 因此,為避免這種情況,您需要稍微向下移動 map - 在這種情況下,用戶位置標記應出現在屏幕底部。 對於 map 中心偏移,您需要獲取當前的 map 中心屏幕坐標,然后更改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));
...

有了所有這些東西,對於您的路線(使用zoom = 15 和tilt = 50 ),您應該得到類似的東西:

方向視圖

如您所見,路線路徑並不完全在路上,因此您需要比 Directions API 響應更精確地獲取路線路徑點。 您可以通過Google Maps Roads API部分Snap to Road獲得該信息

返回給定 GPS 坐標集的最佳擬合道路幾何圖形。 該服務最多需要 100 個沿路線收集的 GPS 點,並返回一組類似的數據,這些點捕捉到車輛行駛的最可能的道路。

就像那個答案一樣。 如果您的路線路徑有多個點,您需要分成 100 個點部分並單獨處理它們(也 Snap to Road API 每個用戶 (IP) 每天有 2500 個請求和每秒 10 個請求。限制)。

正如賈斯萬特·辛格回答你的那樣:

每次調用 onLocationChanged() 回調時,需要在當前位置設置自定義標記(圖標與藍色箭頭相同)並將其移動到新位置(還將相機動畫到該新位置)。

此外,您需要 select zoomtilt屬性,例如,當前用戶速度:當用戶駕駛更快時tilt -> 0 等等。 這不是一項簡單的任務。

Android 沒有為開發提供像定向View (圖 2)這樣的View 。如果您想使用相同的View ,您可以通過像這樣傳遞源位置和目標位置從您的應用程序啟動默認的 map 應用程序。

Intent intent = new Intent(android.content.Intent.ACTION_VIEW, 
    Uri.parse("http://maps.google.com/maps?saddr=20.344,34.34&daddr=20.5666,45.345"));
startActivity(intent);

使用默認的 Android MapView ,您只能使用標記在兩個位置之間添加折線(您可以在許多著名的交付應用程序中看到這一點)。 MapView支持相機縮放,您也可以傾斜(傾斜)Map,但是它不會給出確切的結果。

除了 Jinesh 的回答,如果您仍想添加該標記進行開發,您需要在當前位置設置自定義標記(圖標與藍色箭頭相同),並在每次出現 onLocationChanged( ) 回調被調用(還將相機動畫到該新位置)。 並稍微傾斜 map 以獲得谷歌地圖導航視圖的確切外觀,雖然您不會使用所有功能,但值得一試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM