How to create direction arrows for my polylines in

2019-01-15 22:41发布

问题:

what i need to add for

PolylineOptions polyline = new PolylineOptions();
polyline.addAll(geom);
polyline.color(defaultStrokeColor).width(defaultWidth);
mapObjects.add(polyline);

this code to display the arrow head?

回答1:

I have seen other questions/answers about this that use markers and rotate them. But there is a simpler way to have directional arrows on GoogleMap Polylines.

The GoogleMap API v2 provides a slick way to do this by adding an "endcap" icon to the PolylineOptions. It takes your input bitmap icon and rotates it in the direction of your Polyline. No markers necessary for the arrowheads. And the icon rotation is automatic. As long as the original arrow icon is pointed "up".

Frankly I'm surprised that there is no ArrowCap class. These classes do exist: ButtCap, RoundCap, SquareCap, but not the ArrowCap class.

So we need to slug it out with our own arrow image. The only slight gotcha is that the Polyline (and the next connected Polyline) use the CENTER of the icon as the endpoint. So make sure your endcap icon has it's point at the center of the image.

I made and uploaded a sample arrow icon image here: <>

Sorry that it's white and looks invisible, but it IS there between the < > symbols, just drag it to your desktop.

I wanted to be able to change the arrow color programmatically so I created this white PNG image and then used a color filter to overlay (MULTIPLY) a color onto it.

The icon is a white arrow, pointing up, with the point at the CENTER of image. The top half of the image is empty (transparent). You will want to use Image Asset Studio (or your favorite image tool) to create mipmap images for these resolutions: mdpi=24x24, hdpi=36x36, xhdpi=48x48, xxhdpi=72x72, xxxhdpi=96x96.

Here is the code to generate the endcap BitmapDescriptor needed by the Polyline/PolylineOptions (R.mipmap.endcap is the image I included above):

/**
 * Return a BitmapDescriptor of an arrow endcap icon for the passed color.
 * 
 * @param context - a valid context object
 * @param color - the color to make the arrow icon
 * @return BitmapDescriptor - the new endcap icon
 */
public BitmapDescriptor getEndCapIcon(Context context,  int color) {

    // mipmap icon - white arrow, pointing up, with point at center of image
    // you will want to create:  mdpi=24x24, hdpi=36x36, xhdpi=48x48, xxhdpi=72x72, xxxhdpi=96x96
    Drawable drawable = ContextCompat.getDrawable(context, R.mipmap.endcap);

    // set the bounds to the whole image (may not be necessary ...)
    drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());

    // overlay (multiply) your color over the white icon
    drawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY);

    // create a bitmap from the drawable
    android.graphics.Bitmap bitmap = android.graphics.Bitmap.createBitmap(drawable.getIntrinsicWidth(),
            drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);

    // render the bitmap on a blank canvas
    Canvas canvas = new Canvas(bitmap);
    drawable.draw(canvas);

    // create a BitmapDescriptor from the new bitmap
    return BitmapDescriptorFactory.fromBitmap(bitmap);
}

And here is the code to create the Polyline with an arrow endcap that points in the direction of the Polyline:

/**
 * Draw a GoogleMap Polyline with an endcap arrow between the 2 locations.
 *
 * @param context - a valid context object
 * @param googleMap - a valid googleMap object
 * @param fromLatLng - the starting position
 * @param toLatLng - the ending position
 * @return Polyline - the new Polyline object
 */
public Polyline drawPolylineWithArrowEndcap(Context context,
                                            GoogleMap googleMap,
                                            LatLng fromLatLng,
                                            LatLng toLatLng) {

    int arrowColor = Color.RED; // change this if you want another color (Color.BLUE)
    int lineColor = Color.RED;

    BitmapDescriptor endCapIcon = getEndCapIcon(context,arrowColor);

    // have googleMap create the line with the arrow endcap
    // NOTE:  the API will rotate the arrow image in the direction of the line
    Polyline polyline = googleMap.addPolyline(new PolylineOptions()
            .geodesic(true)
            .color(lineColor)
            .width(8)
            .startCap(new RoundCap())
            .endCap(new CustomCap(endCapIcon,8))
            .jointType(JointType.ROUND)
            .add(fromLatLng, toLatLng);

    return polyline;
}


回答2:

i found a solution , it is working for me

PolylineOptions polyline = new PolylineOptions();
polyline.addAll(geom);
polyline.color(defaultStrokeColor).width(defaultWidth);
mapObjects.add(polyline);
double lat1 = geom.get(0).latitude;
                    double lng1 = geom.get(0).longitude;

                    // destination
                    double lat2 = geom.get(1).latitude;
                    double lng2 = geom.get(1).longitude;

                    //midpoint 
                    double lat = (lat1 + lat2)/2;
                    double lng = (lng1 + lng2)/2;

                    double dLon = (lng2-lng1);
                    double y = Math.sin(dLon) * Math.cos(lat2);
                    double x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
                    double brng = Math.toDegrees((Math.atan2(y, x)));

and now add a marker(arrowhead bitmap) at end point

MarkerOptions marker = new MarkerOptions().position(geom.get(0));
                    marker.anchor(0.5f, 0.5f);
                    marker.icon(BitmapDescriptorFactory.fromBitmap(bstyle));
                    marker.rotation((float) brng);
                    marker.flat(true);


回答3:

The following code applies a round cap to the end of the line, and a different start cap depending on the polyline's type i.e arrow image from a drawable resource file, where the type is an arbitrary property stored in the data object for the polyline. The sample also specifies a stroke width, stroke color, and joint type:

switch (type) {
    // If no type is given, allow the API to use the default.
    case "A":
        // Use a custom bitmap as the cap at the start of the line.
        polyline.setStartCap(
                new CustomCap(
                        BitmapDescriptorFactory.fromResource(R.drawable.ic_arrow), 10));
        break;
    case "B":
        // Use a round cap at the start of the line.
        polyline.setStartCap(new RoundCap());
        break;
}

polyline.setEndCap(new RoundCap());
polyline.setWidth(POLYLINE_STROKE_WIDTH_PX);
polyline.setColor(COLOR_BLACK_ARGB);
polyline.setJointType(JointType.ROUND);

}