MyLocationOverlay - Custom image, but no shadow

2019-08-17 06:00发布

问题:

I have an application, which uses a custom implementation of MyLocationOverlay.

In the implementation I set a Bitmap property that is used when it has been specified, by an overload of Draw.

It works nicely, using my custom image, but it doesn't display a shadow - as is done automatically in an ItemizedOverlay.

Can anyone help?

Here is (the relevant code from) my class:

public class LocationOverlay: MyLocationOverlay
{
    /// <summary>Bitmap to use for indicating the current fixed location.</summary>
    public Bitmap LocationMarker { get; set; }

    /// <summary>Uses the custom marker bitmap if one has been specified. Otherwise, the default is used.</summary>
    /// <param name="canvas"></param>
    /// <param name="mapView"></param>
    /// <param name="shadow"></param>
    /// <param name="when"></param>
    /// <returns></returns>
    public override bool Draw(Canvas canvas, MapView mapView, bool shadow, long when)
    {
        var drawShadow = shadow;

        if (LocationMarker != null && LastFix != null)
        {
            var screenPoint = new Point();
            var geoPoint = new GeoPoint((int)(LastFix.Latitude * 1E6), (int)(LastFix.Longitude * 1E6));
            mapView.Projection.ToPixels(geoPoint, screenPoint);
            canvas.DrawBitmap(LocationMarker, screenPoint.X, screenPoint.Y - 32, null);
            drawShadow = true;
        }

        base.Draw(canvas, mapView, drawShadow);
        return true;
    }
}

回答1:

I think you're missing the point of the shadow argument. The map calls your draw() method twice and it tells you whether this is the shadow pass or not. It doesn't draw the shadow for you. So your code will look something like this:

public override bool Draw(Canvas canvas, MapView mapView, bool shadow, long when)
{
    if (LocationMarker != null && LastFix != null)
    {
        var screenPoint = new Point();
        var geoPoint = new GeoPoint((int)(LastFix.Latitude * 1E6), (int)(LastFix.Longitude * 1E6));
        mapView.Projection.ToPixels(geoPoint, screenPoint);

        if(shadow)
        {
            // Draw your shadow bitmap here
        }
        else
        {
            canvas.DrawBitmap(LocationMarker, screenPoint.X, screenPoint.Y - 32, null);
        }
    }

    return true;
}


回答2:

Got it. You can use DrawAt to draw the shadow automatically.

So my property becomes a Drawable thusly:

public Drawable MarkerResource
{
    set
    {
        _locationMarker = value;
        var widthOffset = _locationMarker.IntrinsicWidth / 2;
        _locationMarker.SetBounds(-widthOffset, -_locationMarker.IntrinsicHeight, widthOffset, 0);
    }
}

And the override now looks like this:

public override bool Draw(Canvas canvas, MapView mapView, bool shadow, long when)
{
    if (LastFix == null) return false;

    if (_locationMarker != null)
    {
        var screenPoint = new Point();
        var geoPoint = new GeoPoint((int)(LastFix.Latitude * 1E6), (int)(LastFix.Longitude * 1E6));
        mapView.Projection.ToPixels(geoPoint, screenPoint);
        DrawAt(canvas, _locationMarker, screenPoint.X, screenPoint.Y, shadow);
    }
    else if (MyLocation != null) DrawMyLocation(canvas, mapView, LastFix, MyLocation, when);

    if (IsCompassEnabled) DrawCompass(canvas, Orientation);
    return false;
}

Works perfectly.

This also now respects enabling the compass and will draw using the default technique if no Drawable is specified.