问题描述
我已经从官方网站的示例中实现了自定义渲染器,但我确实需要每个引脚发送不同的图像.图像将通过 API 作为 base64 字符串.我真的需要为 android 和 iOS 实现.
I've implemented custom renderers from an example from the official site, but I really need for each pin to send different image. Image would come through API as base64 string. I really need implementation for android and iOS.
案例场景:我正在将 CustomPins 加载到地图上.CustomPins 具有不同的字段,例如:Height、Width、NumberOfParticipants、Image1、Image2
case scenario:Im loading CustomPins to the map. CustomPins have different fileds such as: Height, Width, NumberOfParticipants, Image1, Image2
例如我现在拥有的:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MyApp.Droid.Renderers
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public CustomMapRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
}
}
protected override void OnMapReady(GoogleMap map)
{
base.OnMapReady(map);
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(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.FromResource(Resource.Drawable.pin));
return marker;
}
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
var customPin = GetCustomPin(e.Marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
if (!string.IsNullOrWhiteSpace(customPin.Url))
{
var url = Android.Net.Uri.Parse(customPin.Url);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
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");
}
if (customPin.Name.Equals("Xamarin"))
{
view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
}
else
{
view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
}
var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
if (infoTitle != null)
{
infoTitle.Text = marker.Title;
}
if (infoSubtitle != null)
{
infoSubtitle.Text = marker.Snippet;
}
return view;
}
return null;
}
public Android.Views.View GetInfoWindow(Marker marker)
{
return null;
}
CustomPin GetCustomPin(Marker annotation)
{
var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
foreach (var pin in customPins)
{
if (pin.Position == position)
{
return pin;
}
}
return null;
}
}
}
所以,现在,我从我的布局文件夹(xml 结构)中展示我的 InfoWindow:
So, now, Im presenting my InfoWindow from my layout folder (xml strucutre):
<?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="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/xamarin" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/monkey" />
<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:text="InfoWindowTitle"
android:textColor="@android:color/black"
android:textStyle="bold" />
<TextView
android:id="@+id/InfoWindowSubtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="InfoWindowSubtitle"
android:textColor="@android:color/black" />
</LinearLayout>
<ImageButton
android:id="@+id/InfoWindowButton"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:src="@drawable/info" />
</LinearLayout>
</LinearLayout>
那么,有没有办法在运行时将资源图像更改为其他来源?或者我需要做一些不同的事情?
So, is there a way that in a runtime I changed resource image to some other source? Or I need something different to do?
这是一个android的例子,我也需要一个iOS的渲染器例子
This is an example for android, also I need renderer example for iOS too
更新:有没有办法动态生成布局?因为我会有不同类型的引脚 - 每种类型都有不同的 InfoWindow
UPDATE:Is there a way to generate layout also dynamically? Because I would have different types of pins - each type would be having a different InfoWindow
推荐答案
从共享代码中,您还可以在运行时中的 GetInfoContents
方法中更改资源图像.
From shared code ,you also can change the resource image in GetInfoContents
method in a runtime .
var formsMap;
...
formsMap = (CustomMap)e.NewElement;
...
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");
}
if (customPin.Name.Equals("Xamarin"))
{
view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
}
else
{
view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
}
var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
// init imageButton here
var imageButton = view.FindViewById<ImageButton>(Resource.Id.InfoWindowButton);
if (infoTitle != null)
{
infoTitle.Text = marker.Title;
}
if (infoSubtitle != null)
{
infoSubtitle.Text = marker.Snippet;
}
if (imageButton != null)
{
var resourcePath = formsMap.ImageSourcePath;
if (resourcePath == "1"){
imageButton.SetImageResource(Resource.Drawable.IconOne);
}else if (resourcePath == "1"){
imageButton.SetImageResource(Resource.Drawable.IconTwo);
}
// or use url image source
var imageBitmap = GetImageBitmapFromUrl(resourcePath);
imageButton.SetImageBitmap(imageBitmap);
}
return view;
}
return null;
}
那需要CustomMap声明一个ImageSourcePath
属性,不管是要加载Resources Image还是url image,他们都可以做到这一点.
That needs CustomMap to declare a ImageSourcePath
property , no matter want to load Resources Image or url image , they all can achieve that .
public class CustomMap : Map
{
...
public static readonly BindableProperty ImageSourcePathProperty = BindableProperty.Create("ImageSourcePath", typeof(string), typeof(CustomMap), null);
public string ImageSourcePath
{
get { return (string)GetValue(ImageSourcePathProperty); }
set { SetValue(ImageSourcePathProperty, value); }
}
...
}
这篇关于Xamarin Forms Maps 将图像动态添加到 InfoWindow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!