Android 在带有方向路径的 google 地图上绘制带箭头的多段线

Android Draw polylines with arrow on google map with direction path

我添加了多段线,但无法在 google 地图上添加带方向的箭头,应显示如下

当它放大时,应该会显示更多箭头,如下所示

我尝试阅读了各种博客和代码,但未能达到目标

我使用了下面的代码片段:

private void DrawArrowHead(MarkerOptions MO, GoogleMap mMap, LatLng from, LatLng to) {
        // obtain the bearing between the last two points
        double bearing = GetBearing(from, to);

        // round it to a multiple of 3 and cast out 120s
        double adjBearing = Math.round(bearing / 3) * 3;
        while (adjBearing >= 120) {
            adjBearing -= 120;
        }

        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        // Get the corresponding triangle marker from Google
        URL url;
        Bitmap image = null;

        try {
            url = new URL("http://www.google.com/intl/en_ALL/mapfiles/dir_" + String.valueOf((int) adjBearing) + ".png");
            try {
//                image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
                Log.d("HistoryDisplay", String.valueOf(adjBearing));
//                image = BitmapFactory.decodeResource(getResources(), R.drawable.arrow);
                image = BitmapFactory.decodeResource(getResources(), allArrow.get((int) adjBearing));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (image != null) {

            // Anchor is ratio in range [0..1] so value of 0.5 on x and y will center the marker image on the lat/long
            float anchorX = 0.5f;
            float anchorY = 0.5f;

            int offsetX = 0;
            int offsetY = 0;

            // images are 24px x 24px
            // so transformed image will be 48px x 48px

            //315 range -- 22.5 either side of 315
            if (bearing >= 292.5 && bearing < 335.5) {
                offsetX = 24;
                offsetY = 24;
            }
            //270 range
            else if (bearing >= 247.5 && bearing < 292.5) {
                offsetX = 24;
                offsetY = 12;
            }
            //225 range
            else if (bearing >= 202.5 && bearing < 247.5) {
                offsetX = 24;
                offsetY = 0;
            }
            //180 range
            else if (bearing >= 157.5 && bearing < 202.5) {
                offsetX = 12;
                offsetY = 0;
            }
            //135 range
            else if (bearing >= 112.5 && bearing < 157.5) {
                offsetX = 0;
                offsetY = 0;
            }
            //90 range
            else if (bearing >= 67.5 && bearing < 112.5) {
                offsetX = 0;
                offsetY = 12;
            }
            //45 range
            else if (bearing >= 22.5 && bearing < 67.5) {
                offsetX = 0;
                offsetY = 24;
            }
            //0 range - 335.5 - 22.5
            else {
                offsetX = 12;
                offsetY = 24;
            }

            Bitmap wideBmp;
            Canvas wideBmpCanvas;
            Rect src, dest;

            // Create larger bitmap 4 times the size of arrow head image
            wideBmp = Bitmap.createBitmap(image.getWidth() * 2, image.getHeight() * 2, image.getConfig());

            wideBmpCanvas = new Canvas(wideBmp);

            src = new Rect(0, 0, image.getWidth(), image.getHeight());
            dest = new Rect(src);
            dest.offset(offsetX, offsetY);
            wideBmpCanvas.drawBitmap(image, src, dest, null);
//            MO.position(to);
            MO.icon(BitmapDescriptorFactory.fromBitmap(wideBmp));
            MO.anchor(anchorX, anchorY);

            mMap.addMarker(MO);
//            mMap.addMarker(new MarkerOptions()
//                    .position(to)
//                    .icon(BitmapDescriptorFactory.fromBitmap(wideBmp))
//                    .anchor(anchorX, anchorY));
        }

    }

    private double GetBearing(LatLng from, LatLng to) {
        double lat1 = from.latitude * Math.PI / 180.0;
        double lon1 = from.longitude * Math.PI / 180.0;
        double lat2 = to.latitude * Math.PI / 180.0;
        double lon2 = to.longitude * Math.PI / 180.0;

        // Compute the angle.
        double angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));

        if (angle < 0.0)
            angle += Math.PI * 2.0;

        // And convert result to degrees.
        angle = angle * degreesPerRadian;

        return angle;
    }

绘制箭头的最佳方法是在地图上使用 'Marker' 并将其定位在与线的终点或起点相同的位置。您需要将其放平并手动设置其旋转。

幸运的是,Google Maps Utils 可以帮助计算航向(旋转)。

只需将 compile 'com.google.maps.android:android-maps-utils:0.3.4' 添加为 build.gradle 文件中的依赖项

public static void double computeHeading(LatLng from, LatLng to)

使用Double HeadingRotation = SphericalUtil.computeHeading(LatLng from, LatLng to)

将值(以度为单位)设置为标记旋转。

箭头可以是简单的位图,或者更好的是可绘制的 Shape

另请参阅:Google Map Android API Utility