如何在Android Google Map SDK V2中绘制虚线折线?

25

我已经查看了折线的文档,但并没有选项让它成为虚线。

有人知道如何使用Android Google Map SDK v2绘制虚线折线吗?

4个回答

29

现在在 Polyline 中,您可以将图案设置为 Dash、Dot 或 Gap,只需应用以下内容即可。

public static final int PATTERN_DASH_LENGTH_PX = 20;
public static final int PATTERN_GAP_LENGTH_PX = 20;
public static final PatternItem DOT = new Dot();
public static final PatternItem DASH = new Dash(PATTERN_DASH_LENGTH_PX);
public static final PatternItem GAP = new Gap(PATTERN_GAP_LENGTH_PX);
public static final List<PatternItem> PATTERN_POLYGON_ALPHA = Arrays.asList(GAP, DASH);

 private void drawDashedLeg(GoogleMap googleMap, Route route) {
    PolylineOptions polyOptions = new PolylineOptions();
    polyOptions.color(ContextCompat.getColor(getContext(), R.color.coolgrey));
    polyOptions.addAll(route.getPoints());
    polyOptions.pattern(PATTERN_POLYGON_ALPHA);
    Polyline polyline = googleMap.addPolyline(polyOptions);
    polylines.add(polyline);
}

1
@atabouraya 谢谢兄弟 - Gowthaman M

15

这篇回答被标记为“被接受的答案”,其“更新说明”中引用了以下内容:“Google在Google Maps Android API v2中为折线实现了此功能……”。这是不正确的。它不是v2的额外支持或扩展。真正的情况是,他们发布了新的地图API V.10.2.1(02/2017),解决了问题4633,为折线提供了模式(虚线/点线等)。它绝不会仍然支持v2。要使用它,您必须用新版本替换整个v2,并可能重新编写您的地图类实现。 - Panini Luncher
感谢您发布的网址https://maps-apis.googleblog.com/2017/02/styling-and-custom-data-for-polylines.html对我非常有帮助,也解决了我的问题。 - Jatinkumar Patel
1
我已经查看了文档,但是没有找到如何将折线的虚线舍入的方法。有没有什么办法可以实现这个功能呢? - Fazal Hussain

14

Alexey,我刚刚创建了一个对我有用的函数,我认为它会对你有所帮助:

public static void createDashedLine(GoogleMap map, LatLng latLngOrig, LatLng latLngDest, int color){
    double difLat = latLngDest.latitude - latLngOrig.latitude;
    double difLng = latLngDest.longitude - latLngOrig.longitude;

    double zoom = map.getCameraPosition().zoom;

    double divLat = difLat / (zoom * 2);
    double divLng = difLng / (zoom * 2);

    LatLng tmpLatOri = latLngOrig;

    for(int i = 0; i < (zoom * 2); i++){
        LatLng loopLatLng = tmpLatOri;

        if(i > 0){
            loopLatLng = new LatLng(tmpLatOri.latitude + (divLat * 0.25f), tmpLatOri.longitude + (divLng * 0.25f));
        }

        Polyline polyline = map.addPolyline(new PolylineOptions()
            .add(loopLatLng)
            .add(new LatLng(tmpLatOri.latitude + divLat, tmpLatOri.longitude + divLng))
            .color(color)
            .width(5f));

        tmpLatOri = new LatLng(tmpLatOri.latitude + divLat, tmpLatOri.longitude + divLng);
    }
}

嗨,我正在使用相同的方法,它运行良好。但是缩放时,虚线也变得更大了。你知道在缩放时它是否显示相同大小的虚线吗? - user
1
@user,一个解决方案可能是创建一个列表来存储所有组成我们的“虚线”的折线(List<Polyline>),并创建一个方法来设置该列表中所有折线的宽度以适应每个缩放级别。 - Edgar
当你有很多行(1k)时,这种方法会使应用程序变慢吗? - Roberto Lombardini
这种方法即使在现代手机上也很慢,计算速度很慢,即使它似乎是使用v2 API唯一可能的方法。 - Zorb
这个很好用,但是如何清除带有更新的行? - portfoliobuilder

9
我创建了以下函数来绘制由LatLng点列表组成的虚线折线。该算法创建0.002公里的线段(后跟0.002公里的间隔),不受缩放影响。当您不想在缩放更改时重新绘制折线时,这非常有用。
private void drawDashedPolyLine(GoogleMap mMap, ArrayList<LatLng> listOfPoints, int color) {
    /* Boolean to control drawing alternate lines */
    boolean added = false;
    for (int i = 0; i < listOfPoints.size() - 1 ; i++) {
        /* Get distance between current and next point */
        double distance = getConvertedDistance(listOfPoints.get(i),listOfPoints.get(i + 1));

        /* If distance is less than 0.002 kms */
        if (distance < 0.002) {
            if (!added) {
                mMap.addPolyline(new PolylineOptions()
                        .add(listOfPoints.get(i))
                        .add(listOfPoints.get(i + 1))
                        .color(color));
                added = true;
            } else {/* Skip this piece */
                added = false;
            }
        } else {
            /* Get how many divisions to make of this line */
            int countOfDivisions = (int) ((distance/0.002));

            /* Get difference to add per lat/lng */
            double latdiff = (listOfPoints.get(i+1).latitude - listOfPoints
                    .get(i).latitude) / countOfDivisions;
            double lngdiff = (listOfPoints.get(i + 1).longitude - listOfPoints
                    .get(i).longitude) / countOfDivisions;

            /* Last known indicates start point of polyline. Initialized to ith point */
            LatLng lastKnowLatLng = new LatLng(listOfPoints.get(i).latitude, listOfPoints.get(i).longitude);
            for (int j = 0; j < countOfDivisions; j++) {

                /* Next point is point + diff */
                LatLng nextLatLng = new LatLng(lastKnowLatLng.latitude + latdiff, lastKnowLatLng.longitude + lngdiff);
                if (!added) {
                    mMap.addPolyline(new PolylineOptions()
                    .add(lastKnowLatLng)
                    .add(nextLatLng)
                    .color(color));
                    added = true;
                } else {
                    added = false;
                }
                lastKnowLatLng = nextLatLng;
            }
        }
    }
}

private double getConvertedDistance(LatLng latlng1, LatLng latlng2) {
    double distance = DistanceUtil.distance(latlng1.latitude,
            latlng1.longitude,
            latlng2.latitude,
            latlng2.longitude);
    BigDecimal bd = new BigDecimal(distance);
    BigDecimal res = bd.setScale(3, RoundingMode.DOWN);
    return res.doubleValue();
}

这是一个用于计算两个经纬度之间距离的实用类:

public class DistanceUtil {

    public static double distance(double lat1, double lon1, double lat2,
        double lon2) {

    if ((lat1 == lat2) && (lon1 == lon2)) {
        return 0;
    } else
        return distance(lat1, lon1, lat2, lon2, 'K');
    }

    public static double distance(double lat1, double lon1, double lat2,
        double lon2, char unit) {
        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;
        if (unit == 'K') {
            dist = dist * 1.609344;
        } else if (unit == 'N') {
            dist = dist * 0.8684;
        }
        return (dist);
    }

    private static double deg2rad(double deg) {
        return (deg * Math.PI / 180.0);
    }

    private static double rad2deg(double rad) {
        return (rad * 180.0 / Math.PI);
    }
}

注意:上述算法生成的折线数量非常大,可能需要很长时间才能渲染完毕。仅在点列表较小的情况下才有用。

我在循环中使用了您的算法,以0.02公里为单位,并增加了变量k:if(k%2== 0){addPopyline ..} 以获取黑白虚线。 - djdance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接