diff --git a/src/Controls/Maps/src/ClusterInfo.cs b/src/Controls/Maps/src/ClusterInfo.cs new file mode 100644 index 000000000000..8d8543a1b4f2 --- /dev/null +++ b/src/Controls/Maps/src/ClusterInfo.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Microsoft.Maui.Devices.Sensors; + +namespace Microsoft.Maui.Controls.Maps +{ + /// + /// Describes a pin cluster, passed to an image provider callback so the + /// application can produce a custom icon for the cluster marker. + /// + public sealed class ClusterInfo + { + IReadOnlyList? _pins; + readonly Func>? _pinsFactory; + string? _clusteringIdentifier; + readonly Func? _clusteringIdentifierFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The number of pins in the cluster. + /// The clustering identifier shared by the cluster's pins. + /// The pins contained in the cluster. + /// The geographic location (centroid) of the cluster. + public ClusterInfo(int count, string clusteringIdentifier, IReadOnlyList pins, Location location) + { + Count = count; + _clusteringIdentifier = clusteringIdentifier ?? throw new ArgumentNullException(nameof(clusteringIdentifier)); + _pins = pins ?? throw new ArgumentNullException(nameof(pins)); + Location = location ?? throw new ArgumentNullException(nameof(location)); + } + + // Lazy path used by the handler: defers the O(members × pins) resolution until the provider + // actually reads Pins/ClusteringIdentifier, so a count-only provider pays nothing. + internal ClusterInfo(int count, Location location, Func> pinsFactory, Func clusteringIdentifierFactory) + { + Count = count; + Location = location; + _pinsFactory = pinsFactory; + _clusteringIdentifierFactory = clusteringIdentifierFactory; + } + + /// Gets the number of pins contained in the cluster. + /// This is the authoritative member count, independent of how many entries holds. + public int Count { get; } + + /// Gets the clustering identifier shared by the pins in this cluster. + /// Falls back to when no member pin could be resolved. + public string ClusteringIdentifier => _clusteringIdentifier ??= _clusteringIdentifierFactory!(); + + /// Gets the pins contained in this cluster. + /// + /// On some platforms (iOS) not every cluster member can be resolved back to a , + /// so this list can contain fewer than entries - use for badge numbers. + /// + public IReadOnlyList Pins => _pins ??= _pinsFactory!(); + + /// Gets the geographic location (centroid) of the cluster. + public Location Location { get; } + } +} diff --git a/src/Controls/Maps/src/HandlerImpl/Map.Impl.cs b/src/Controls/Maps/src/HandlerImpl/Map.Impl.cs index 8800d90b192d..2fa2c981cdad 100644 --- a/src/Controls/Maps/src/HandlerImpl/Map.Impl.cs +++ b/src/Controls/Maps/src/HandlerImpl/Map.Impl.cs @@ -1,11 +1,14 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Maui.Devices.Sensors; using Microsoft.Maui.Maps; namespace Microsoft.Maui.Controls.Maps { - public partial class Map : IMap, IEnumerable + public partial class Map : IMap, IMapClusterImageProvider, IEnumerable { IList IMap.Elements => _mapElements.Cast().ToList(); @@ -13,6 +16,8 @@ public partial class Map : IMap, IEnumerable Location? IMap.LastUserLocation => _lastUserLocation; + int IMapClusterImageProvider.ClusterImageVersion => _clusterImageVersion; + void IMap.Clicked(Location location) => MapClicked?.Invoke(this, new MapClickedEventArgs(location)); bool IMap.ClusterClicked(IReadOnlyList pins, Location location) @@ -24,6 +29,39 @@ bool IMap.ClusterClicked(IReadOnlyList pins, Location location) return args.Handled; } + Microsoft.Maui.IImageSource? IMapClusterImageProvider.GetClusterImage(IReadOnlyList pins, int count, Location location) + { + var provider = ClusterImageProvider; + if (provider is not null) + { + // The provider is app code invoked from platform callbacks (a native MapKit delegate on + // iOS, a fire-and-forget task on Android) where an unhandled exception either crashes the + // app or silently drops the cluster marker - degrade to the static/default icon instead. + try + { + // Pins/identifier are resolved lazily: a provider that only reads Count (like the + // sample) never triggers the platform's O(members × pins) resolution scan. + var image = provider(new ClusterInfo(count, location, + () => pins.OfType().ToList(), + () => + { + foreach (var pin in pins) + if (pin is Pin controlPin) + return controlPin.ClusteringIdentifier ?? Pin.DefaultClusteringIdentifier; + return Pin.DefaultClusteringIdentifier; + })); + if (image is not null) + return image; + } + catch (Exception ex) + { + Handler?.MauiContext?.Services?.GetService>()?.LogWarning(ex, "ClusterImageProvider threw; falling back to the static or default cluster icon"); + } + } + + return ClusterImageSource; + } + void IMap.UserLocationUpdated(Location location) { if (Equals(_lastUserLocation, location)) diff --git a/src/Controls/Maps/src/Map.cs b/src/Controls/Maps/src/Map.cs index e0c46ab7cd11..9131c6a7190f 100644 --- a/src/Controls/Maps/src/Map.cs +++ b/src/Controls/Maps/src/Map.cs @@ -34,6 +34,11 @@ public partial class Map : View /// Bindable property for . public static readonly BindableProperty IsClusteringEnabledProperty = BindableProperty.Create(nameof(IsClusteringEnabled), typeof(bool), typeof(Map), default(bool)); + /// Bindable property for . + public static readonly BindableProperty ClusterImageSourceProperty = BindableProperty.Create(nameof(ClusterImageSource), typeof(ImageSource), typeof(Map), default(ImageSource), + propertyChanging: (b, o, n) => ((Map)b).OnClusterImageSourceChanging((ImageSource?)o), + propertyChanged: (b, o, n) => ((Map)b).OnClusterImageSourceChanged((ImageSource?)n)); + /// Bindable property for . public static readonly BindableProperty MapStyleProperty = BindableProperty.Create(nameof(MapStyle), typeof(string), typeof(Map), default(string)); @@ -58,6 +63,8 @@ public partial class Map : View MapSpan? _visibleRegion; MapSpan? _lastMoveToRegion; Location? _lastUserLocation; + Func? _clusterImageProvider; + int _clusterImageVersion; /// /// Initializes a new instance of the class with a region. @@ -82,6 +89,14 @@ public Map() : this(new MapSpan(new Devices.Sensors.Location(20.793062527, -156. { } + protected override void OnBindingContextChanged() + { + if (ClusterImageSource is not null) + SetInheritedBindingContext(ClusterImageSource, BindingContext); + + base.OnBindingContextChanged(); + } + /// /// Gets or sets a value that indicates if scrolling by user input is enabled. Default value is . /// This is a bindable property. @@ -139,7 +154,50 @@ public bool IsClusteringEnabled } /// - /// Gets or sets the style of the map. Default value is . + /// Gets or sets a static custom icon used for every cluster marker when clustering is enabled. + /// Ignored if returns a non-null image for a cluster. + /// When (and no provider image is returned) the default cluster marker is used. + /// This is a bindable property. + /// + /// + /// No pin count is drawn over the image. Each platform scales it to a marker-sized icon + /// (Android fits within 64 pixels, iOS within 32 points), matching . + /// Changing this value rebuilds existing cluster markers immediately. + /// + public ImageSource? ClusterImageSource + { + get => (ImageSource?)GetValue(ClusterImageSourceProperty); + set => SetValue(ClusterImageSourceProperty, value); + } + + /// + /// Gets or sets a callback that returns a custom icon for a cluster marker, computed from the + /// supplied (count, clustering identifier, pins, location). + /// Return to fall back to , then to the + /// default cluster marker. Only used when clustering is enabled. + /// + /// + /// The callback returns the complete icon (draw the count yourself if desired). The returned + /// is loaded asynchronously by the platform handler, like + /// . Setting this value rebuilds existing cluster markers immediately. + /// + public Func? ClusterImageProvider + { + get => _clusterImageProvider; + set + { + // Delegate.Equals compares target+method, so re-assigning the same method group + // (e.g. from OnAppearing on every navigation) short-circuits instead of rebuilding + // every cluster marker. + if (Equals(_clusterImageProvider, value)) + return; + _clusterImageProvider = value; + OnClusterImageChanged(); + } + } + + /// + /// Gets or sets the style of the map. Default value is . /// This is a bindable property. /// public MapType MapType @@ -333,6 +391,60 @@ void OnRegionPropertyChanged(MapSpan? newRegion) } } + void OnClusterImageSourceChanging(ImageSource? oldSource) + { + if (oldSource is null) + return; + + CancelOldClusterImageSource(oldSource); + oldSource.SourceChanged -= OnClusterImageSourceSourceChanged; + oldSource.Parent = null; + SetInheritedBindingContext(oldSource, null); + } + + void OnClusterImageSourceChanged(ImageSource? newSource) + { + if (newSource is not null) + { + newSource.SourceChanged += OnClusterImageSourceSourceChanged; + newSource.Parent = this; + SetInheritedBindingContext(newSource, BindingContext); + } + + OnClusterImageChanged(); + } + + void OnClusterImageSourceSourceChanged(object? sender, EventArgs e) => OnClusterImageChanged(); + + async void CancelOldClusterImageSource(ImageSource oldSource) + { + try + { + await oldSource.Cancel(); + } + catch (ObjectDisposedException) + { + } + } + + // Rebuild pins/clusters so a changed ClusterImageSource/ClusterImageProvider is reflected + // immediately, instead of waiting for the next unrelated recluster (e.g. a zoom). + void OnClusterImageChanged() + { + unchecked + { + _clusterImageVersion++; + } + + // Cluster images are only consumed while clustering is on; enabling clustering later + // re-runs the pins mapper anyway (MapIsClusteringEnabled calls MapPins on both + // platforms), so nothing is lost by skipping the rebuild here. + if (!IsClusteringEnabled) + return; + + Handler?.UpdateValue(nameof(IMap.Pins)); + } + void PinsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems is not null && e.NewItems.Cast().Any(pin => pin.Label is null)) diff --git a/src/Controls/Maps/src/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net-android/PublicAPI.Unshipped.txt index afb23c4a7a8b..8cbb399e9fcf 100644 --- a/src/Controls/Maps/src/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -1,5 +1,4 @@ #nullable enable - Microsoft.Maui.Controls.Maps.Circle.CircleClicked -> System.EventHandler? Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.ClusterClickedEventArgs(System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void @@ -7,7 +6,17 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -34,6 +43,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt index afb23c4a7a8b..8cbb399e9fcf 100644 --- a/src/Controls/Maps/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -1,5 +1,4 @@ #nullable enable - Microsoft.Maui.Controls.Maps.Circle.CircleClicked -> System.EventHandler? Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.ClusterClickedEventArgs(System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void @@ -7,7 +6,17 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -34,6 +43,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index afb23c4a7a8b..8cbb399e9fcf 100644 --- a/src/Controls/Maps/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -1,5 +1,4 @@ #nullable enable - Microsoft.Maui.Controls.Maps.Circle.CircleClicked -> System.EventHandler? Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.ClusterClickedEventArgs(System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void @@ -7,7 +6,17 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -34,6 +43,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index afb23c4a7a8b..51bb52730870 100644 --- a/src/Controls/Maps/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -1,6 +1,12 @@ #nullable enable Microsoft.Maui.Controls.Maps.Circle.CircleClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.ClusterClickedEventArgs(System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool @@ -8,6 +14,10 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -34,6 +44,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt index afb23c4a7a8b..51bb52730870 100644 --- a/src/Controls/Maps/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -1,6 +1,12 @@ #nullable enable Microsoft.Maui.Controls.Maps.Circle.CircleClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.ClusterClickedEventArgs(System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool @@ -8,6 +14,10 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -34,6 +44,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/net/PublicAPI.Unshipped.txt index b7563d703b56..8cbb399e9fcf 100644 --- a/src/Controls/Maps/src/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/net/PublicAPI.Unshipped.txt @@ -6,7 +6,17 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -33,6 +43,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/Maps/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/Maps/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt index b7563d703b56..8cbb399e9fcf 100644 --- a/src/Controls/Maps/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/Maps/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -6,7 +6,17 @@ Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.get -> bool Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Handled.set -> void Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.ClusterClickedEventArgs.Pins.get -> System.Collections.Generic.IReadOnlyList! +Microsoft.Maui.Controls.Maps.ClusterInfo +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusterInfo(int count, string! clusteringIdentifier, System.Collections.Generic.IReadOnlyList! pins, Microsoft.Maui.Devices.Sensors.Location! location) -> void +Microsoft.Maui.Controls.Maps.ClusterInfo.ClusteringIdentifier.get -> string! +Microsoft.Maui.Controls.Maps.ClusterInfo.Count.get -> int +Microsoft.Maui.Controls.Maps.ClusterInfo.Location.get -> Microsoft.Maui.Devices.Sensors.Location! +Microsoft.Maui.Controls.Maps.ClusterInfo.Pins.get -> System.Collections.Generic.IReadOnlyList! Microsoft.Maui.Controls.Maps.Map.ClusterClicked -> System.EventHandler? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.get -> System.Func? +Microsoft.Maui.Controls.Maps.Map.ClusterImageProvider.set -> void +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.get -> Microsoft.Maui.Controls.ImageSource? +Microsoft.Maui.Controls.Maps.Map.ClusterImageSource.set -> void Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.get -> bool Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabled.set -> void Microsoft.Maui.Controls.Maps.Map.LastUserLocation.get -> Microsoft.Maui.Devices.Sensors.Location? @@ -33,6 +43,8 @@ Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.Location.get -> Microsoft.Maui.Devices.Sensors.Location! Microsoft.Maui.Controls.Maps.UserLocationChangedEventArgs.UserLocationChangedEventArgs(Microsoft.Maui.Devices.Sensors.Location! location) -> void const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string! +override Microsoft.Maui.Controls.Maps.Map.OnBindingContextChanged() -> void +static readonly Microsoft.Maui.Controls.Maps.Map.ClusterImageSourceProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.IsClusteringEnabledProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.MapStyleProperty -> Microsoft.Maui.Controls.BindableProperty! static readonly Microsoft.Maui.Controls.Maps.Map.RegionProperty -> Microsoft.Maui.Controls.BindableProperty! diff --git a/src/Controls/samples/Controls.Sample/Pages/Controls/MapsGalleries/ClusteringGallery.xaml b/src/Controls/samples/Controls.Sample/Pages/Controls/MapsGalleries/ClusteringGallery.xaml index 0fe56c34aa2f..0f3a965320a9 100644 --- a/src/Controls/samples/Controls.Sample/Pages/Controls/MapsGalleries/ClusteringGallery.xaml +++ b/src/Controls/samples/Controls.Sample/Pages/Controls/MapsGalleries/ClusteringGallery.xaml @@ -8,33 +8,45 @@ mc:Ignorable="d" x:Class="Maui.Controls.Sample.Pages.MapsGalleries.ClusteringGallery" Title="Pin Clustering"> - - -