简体   繁体   中英

Xamarin Forms custom control: implement a method in the renderer

I'm trying to create an extended version of the standard XF Map object:

public class RRMap: Map
{

    public void DoSomethingOnMap() {
        /* ... */
    }

}

I also created an Android renderer (iOS will come later):

[assembly: ExportRenderer(typeof(RRMap), typeof(RRMapRendererAndroid))]
namespace MyApp.Droid.Renderers
{
    public class RRMapRendererAndroid : MapRenderer
    {
        public RRMapRendererAndroid(Context context) : base(context) { }

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                Control.GetMapAsync(this);
            }
        }

        protected override MarkerOptions CreateMarker(Pin pin)
        {
            var marker = new MarkerOptions();
            marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
            marker.SetTitle(pin.Label);
            marker.SetSnippet(pin.Address);
            marker.SetIcon(BitmapDescriptorFactory.DefaultMarker(210));
            return marker;
        }

    }
}

Everything is working fine so far: the map is rendered and pins are created with a custom color.

Unfortunately, I'm stuck on the implementation of DoSomethingOnMap method: it should be a method in the shared code, but it should be implemented in different ways, depending on the platform.

In other circumstances, I would create an interface using DependencyService for implementation, but in this particular case I can't figure out how to proceed.

The first solution is you can use a messaging-center , this can communicate between shared project and iOS/Android project.

Publish a message in the doSomethingOnMap method and anywhere you subscribed to the message will be triggered.

The second is create an event in your shared project and subscribe to that event in the renderer, I wrote both two solutions below:

In your shared project:

public class CustomMap : Map
{
    public List<CustomPin> CustomPins { get; set; }

    public event EventHandler CallToNativeMethod;

    public void doSomething()
    {
        if (CallToNativeMethod != null)
            CallToNativeMethod(this, new EventArgs());
    }

    public void doSomething(CustomMap myMap) {


        MessagingCenter.Send<CustomMap>(this, "Hi");

    }
}

In the renderer:

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {

        }

        if (e.NewElement != null)
        {

            MessagingCenter.Subscribe<CustomMap>(this, "Hi", (sender) =>
            {
                // Do something whenever the "Hi" message is received
                Console.WriteLine("hi");
            });

            ((CustomMap)e.NewElement).CallToNativeMethod += (sender, arg) =>
            {
                Console.WriteLine("native method");
            };
        }
    }

At anywhere you want to call this method:

private void Button_Clicked(object sender, System.EventArgs e)
{
    customMap.doSomething();
    customMap.doSomething(customMap);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM