Search code examples
androidgoogle-mapsgoogle-maps-markersgoogle-maps-android-api-2

How to add shape on top of polylines in Google Maps Android SDK


I have an app containing code to draw polylines between the source and destination points using the Google Maps Android SDK and the Polyline and PolylineOptions classes.

My question is that how can I add a small shape - for example, an arrow pointing from the source to the destination, drawn on the top of the polyline - so that its direction and angle change by zooming and rotating the map UI, much like the standard arrows in popular navigation apps?

Any help would be appreciated.


Solution

  • Anyway, you can create MapView- or MapFragment-based custom view and draw whatever you want (like in this answer). In that case you need to draw polyline on custom view canvas directly, not via using Google Maps Polyline. If you want to draw single arrow at the middle of the path segment you need:

    1. determine direction using, for example, computeHeading() method of SphericalUtil class of Maps SDK for Android Utility Library;

    2. determine middle of path segment, for example, via interpolate() method of SphericalUtil class:

      LatLng middle = interpolate(from, to, 0.5);

    If you want to draw small arrows along all polyline you can customize line styles via can use setPathEffect() method of Paint class. For this You should create path for "arrow stamp" (in pixels), which will repeated every "advance" (in pixels too) - totally like in this example for "diamond":

        mPathDiamondStamp = new Path();
        mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2, 0);
        mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2);
        mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2, 0);
        mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2);
        mPathDiamondStamp.close();
    
        mPathDiamondStamp.moveTo(-DIAMOND_WIDTH / 2 + DIAMOND_BORDER_WIDTH, 0);
        mPathDiamondStamp.lineTo(0, -DIAMOND_HEIGHT / 2 + DIAMOND_BORDER_WIDTH / 2);
        mPathDiamondStamp.lineTo(DIAMOND_WIDTH / 2 - DIAMOND_BORDER_WIDTH, 0);
        mPathDiamondStamp.lineTo(0, DIAMOND_HEIGHT / 2 - DIAMOND_BORDER_WIDTH / 2);
        mPathDiamondStamp.close();
    
        mPathDiamondStamp.setFillType(Path.FillType.EVEN_ODD);
    
        mDiamondPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mDiamondPaint.setColor(Color.BLUE);
        mDiamondPaint.setStrokeWidth(2);
        mDiamondPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mDiamondPaint.setStyle(Paint.Style.STROKE);
        mDiamondPaint.setPathEffect(new PathDashPathEffect(mPathDiamondStamp, DIAMOND_ADVANCE, DIAMOND_PHASE, PathDashPathEffect.Style.ROTATE));
    

    In that case all work for "direction and angle change by zooming and rotating the map UI" processing Paint class do for you "from the box" - you just need to set the "stamp" pattern and intervals between stamps.

    For converting LatLng coordinates into screen coordinates you can use toScreenLocation() of Projection class. So, make custom view based on MapView or SupportMapFragment and draw whatever you want with Canvas and Paint.

    Here and there you can also find good examples of setPathEffect() usage.