1

I'm trying to add the object's image passed to the custom pin in the InfoWindow to the left of the InfoWindow.

I have an app that calls an API and returns an object that has a name and an image and I want the InfoWindow's left icon to be the object's image but I don't know how to do it.

enter image description here

The left image.

Thank you for your help.

For Cole

CustomMapRenderer

public Android.Views.View GetInfoContents(Marker marker)
    {
        var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;
        if (inflater != null)
        {
            Android.Views.View view;

            var customPin = GetCustomPin(marker);
            if (customPin == null)
            {
                throw new Exception("Custom pin not found");
            }

            view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);


            var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
            var infoSubtitle1 = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle1);
            ImageView image = view.FindViewById<ImageView>(Resource.Id.image);

            Task.Run(() => {
                URL url = new URL(customPin.Image);
                var mIcon_val = BitmapFactory.DecodeStream(url.OpenConnection().InputStream);
                image.SetImageBitmap(mIcon_val);
            });

            if (infoTitle != null)
            {
                infoTitle.Text = marker.Title;
            }
            if (infoSubtitle1 != null)
            {
                infoSubtitle1.Text = marker.Snippet;
            }

            return view;
        }
        return null;
    }

MapInfoWindow

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
    android:id="@+id/image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center" />
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_margin="10dp">
    <TextView
        android:id="@+id/InfoWindowTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="InfoWindowTitle"
        android:textColor="@android:color/black"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/InfoWindowSubtitle1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="InfoWindowSubtitle1"
        android:textColor="@android:color/black" />
</LinearLayout>
<ImageButton
    android:id="@+id/InfoWindowButton"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:background="@color/mtrl_btn_transparent_bg_color"
    android:src="@drawable/icon_heart_red_24" />
Jimmy
  • 105
  • 15

1 Answers1

0

Create the custom class that has Name and Image property.

public class CustomPin : Pin
{
    public string Name { get; set; }
    public string Image{ get; set; }
}

Populate the custom pin with the data returned by the API , and add the pin into map.Pins.

 CustomPin pin = new CustomPin
    {
        Type = PinType.Place,
        Position = new Position(37.79752, -122.40183),
        Label = "Xamarin San Francisco Office",
        Address = "394 Pacific Ave, San Francisco CA",       
        Url = "http://xamarin.com/about/",
        Name = "xxxxx",
        Image =  "xxxx";
    };
    customMap.CustomPins = new List<CustomPin> { pin };
    customMap.Pins.Add(pin);

Override CreateMarker method

protected override MarkerOptions CreateMarker(Pin pin)
{
    var marker = new MarkerOptions();

    CustomPin pin2 = pin;

    marker.SetPosition(new LatLng(pin2.Position.Latitude, pin2.Position.Longitude));
    marker.SetTitle(pin2.Label);
    marker.SetSnippet(pin2.Address);

    URL url = new URL(pin2.Image);
    Bitmap bmp = BitmapFactory.DecodeStream(url.OpenConnection().InputStream);
    marker.SetIcon(BitmapDescriptorFactory.FromBitmap(bmp));
    return marker;
}

Update

ImageView image  view.FindViewById<ImageView>(Resource.Id.image);

Task.Run(() => {
     URL url = new URL(customPin.Image);
     var mIcon_val = BitmapFactory.DecodeStream(url.OpenConnection().InputStream);

     MainThread.BeginInvokeOnMainThread(()=> {
        image.SetImageBitmap(mIcon_val);
    });
});
ColeX
  • 14,062
  • 5
  • 43
  • 240
  • Thank you for your answer, I can't use pin.Image because a Pin is passed to the CreateMarker method and not a CustomPin which doesn't have an Image property, how should I do it ? – Jimmy Jun 17 '21 at 20:44
  • Change the parameter in `CreateMarker` method . `protected override MarkerOptions CreateMarker(CustomPin pin)` – ColeX Jun 18 '21 at 01:33
  • I tried but it says "CreateMarker(CustomPin customPin) No suitable method found to override" – Jimmy Jun 18 '21 at 08:58
  • Try to convert to the custom pin , check my update . – ColeX Jun 18 '21 at 09:12
  • Thank you for your help, so I think it will work the thing is I'm getting an exception for the Bitmap bmp = BitmapFactory.DecodeStream(url.OpenConnection().InputStream); line that says Android.OS.NetworkOnMainThreadException and nothing else – Jimmy Jun 18 '21 at 21:41
  • So I think your code creates a different Pin, as in the pin itself but not the image in the InfoWindow which is in the GetInfoContents method – Jimmy Jun 19 '21 at 23:56
  • You can also customize the image used in `GetInfoContents` method , because we can get the custom pin from `var customPin = GetCustomPin(marker);` , and then get its property , you can do anything after then . – ColeX Jun 21 '21 at 07:43
  • So I tried it the only problem I have is that I don't know how to add a dynamic value for the android:src=@drawable/monkey.png value in the InfoWindow.xml file so that it can be the object's image instead of a file – Jimmy Jun 22 '21 at 03:40
  • Where the dynamic comes from ? Is it a remote or local image ? – ColeX Jun 22 '21 at 05:49
  • It is a remote image from an API – Jimmy Jun 22 '21 at 06:05
  • Check my update , refer to https://stackoverflow.com/a/16293557/8187800. – ColeX Jun 22 '21 at 06:18
  • Thank you I'm going to check it out, but should I not put anything for android:src so that the value can be anything I add in the code ? – Jimmy Jun 22 '21 at 06:34
  • if the image is from internet you don't need to set anything on the imageview in xml , just use the code above . – ColeX Jun 22 '21 at 06:38
  • I tried but it doesn't show any icon anymore now that I have taken android:src out of the in xml, and I'm adding the object's image to the CustomPin's image property, the image shows up in other parts of my app but not there – Jimmy Jun 22 '21 at 06:59
  • Could you show the code using `android:src ` in code behind ? – ColeX Jun 22 '21 at 07:02
  • Can you debug on the value `mIcon_val ` to check if it has value , and try to set the image on main thread , check my update . – ColeX Jun 22 '21 at 09:31
  • The values are the following : image = {android.widget.ImageView{512357f V.ED..... ......ID 0,111-0,111 #7f080099 app:id/image}} mIcon_val = {android.graphics.Bitmap@c872138} But nothing is showing even with the updated code – Jimmy Jun 22 '21 at 20:29
  • mIcon_val has a value but it says that image is null after SetImageBitmap – Jimmy Jun 23 '21 at 23:15
  • Check my update , it works fine on my side , change `Device.BeginInvokeOnMainThread` to `MainThread.BeginInvokeOnMainThread` . – ColeX Jun 24 '21 at 09:47
  • It still doesn't work, can you show me you InfoWindow.xaml to make sure I have it right ? And thank you so much for the time you're putting into helping me ! – Jimmy Jun 24 '21 at 23:09
  • Can you provide the image link so that i can test ? – ColeX Jun 25 '21 at 01:19
  • I'd like to but I don't think it's because of the link because I'm using many links from different links and they all load when I load the objects but just not in the custom renderer, maybe it's my InfoWindow.xaml that is missing something – Jimmy Jun 25 '21 at 05:32
  • I use the official axml directly : https://github.com/xamarin/xamarin-forms-samples/blob/main/CustomRenderers/Map/Droid/Resources/layout/MapInfoWindow.axml. – ColeX Jun 25 '21 at 05:48
  • But the official one add android:src and adds a drawable to it – Jimmy Jun 25 '21 at 06:11
  • just remove `src` attribute . – ColeX Jun 25 '21 at 06:56
  • I did, that's why it's weird that nothing is being displayed – Jimmy Jun 25 '21 at 07:59
  • Can you try it in a blank android project ? – ColeX Jun 25 '21 at 08:26
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/234186/discussion-between-colex-msft-and-sacha-person). – ColeX Jun 25 '21 at 08:41