Skip to content

Commit f558ca6

Browse files
authored
feat: BasicLocationPulsingCircleExample (#35)
* - use `is null` expression * - fix(android): move mapready event invocation to MapboxViewFragment.OnViewCreated * - fix(android): AddREmoveAnnotations - move MapboxStyle setup to MapReady * - initial setup for location component on Android * - Toggle Map Style * - add menu items on Android * - add iOS implementation (draft) * - Use bottomsheet instead of toolbar items (not work for iOS) - Correct iOS impl * - add CameraForCoordinates * - iOS impl * - update nuget package * - check and fix iOS binding
1 parent 68456b9 commit f558ca6

25 files changed

+849
-70
lines changed

src/libs/Mapbox.Maui/IMapboxView.cs

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using System.Windows.Input;
44
using MapboxMaui.Annotations;
5+
using MapboxMaui.Locations;
56
using MapboxMaui.Query;
67
using MapboxMaui.Styles;
78
using MapboxMaui.Viewport;
@@ -35,6 +36,8 @@ public partial interface IMapboxView : IView
3536
IMapFeatureQueryable QueryManager { get; }
3637

3738
IViewportPlugin Viewport { get; }
39+
40+
ILocationComponentPlugin LocationComponent { get; }
3841
}
3942

4043
partial interface IMapboxView
@@ -83,6 +86,21 @@ public interface IMapboxController
8386
IPosition GetMapPosition(ScreenPosition position);
8487
CoordinateBounds GetCoordinateBoundsForCamera(CameraOptions cameraOptions);
8588
ScreenPosition GetScreenPosition(IPosition position);
89+
CameraOptions? CameraForCoordinates(
90+
IEnumerable<IPosition> coordinates,
91+
CameraOptions? cameraOptions = default,
92+
Thickness? coordinatesPadding = default,
93+
double? maxZoom = default,
94+
ScreenPosition? offset = default
95+
);
96+
void CameraForCoordinates(
97+
IEnumerable<IPosition> coordinates,
98+
Action<CameraOptions?> completion,
99+
CameraOptions? cameraOptions = default,
100+
Thickness? coordinatesPadding = default,
101+
double? maxZoom = default,
102+
ScreenPosition? offset = default
103+
);
86104
}
87105

88106
public class MapTappedEventArgs : EventArgs

src/libs/Mapbox.Maui/Mapbox.Maui.csproj

+8-2
Original file line numberDiff line numberDiff line change
@@ -61,21 +61,27 @@
6161
<RepositoryUrl>https://github.com/tuyen-vuduc/mapbox-maui</RepositoryUrl>
6262
<PackageProjectUrl>https://mapbox.tuyen-vuduc.tech</PackageProjectUrl>
6363
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
64-
<PackageVersion>11.5.1-alpha02</PackageVersion>
64+
<PackageVersion>11.5.1-alpha03</PackageVersion>
6565
<PackageReadmeFile>README.md</PackageReadmeFile>
6666
<PackageLicenseFile>LICENSE</PackageLicenseFile>
6767
<PackageIcon>tv-mapbox.png</PackageIcon>
6868
</PropertyGroup>
6969
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
7070
<CreatePackage>false</CreatePackage>
7171
</PropertyGroup>
72+
<ItemGroup>
73+
<Compile Remove="Platforms\Android\MapboxViewHandler.Location.cs" />
74+
<Compile Remove="Platforms\iOS\MapboxViewHandler.Location.cs" />
75+
</ItemGroup>
7276
<ItemGroup>
7377
<None Remove="Models\Gestures\" />
7478
</ItemGroup>
7579
<ItemGroup>
7680
<None Include="../../../assets/tv-mapbox.png" Pack="True" PackagePath="tv-mapbox.png" />
7781
<None Include="../../../LICENSE" Pack="True" PackagePath="" />
7882
<None Include="../../../README.md" Pack="True" PackagePath="README.md" />
83+
<None Include="Platforms\Android\MapboxViewHandler.Location.cs" />
84+
<None Include="Platforms\iOS\MapboxViewHandler.Location.cs" />
7985

8086
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
8187
<PackageReference Include="Xamarin.Build.Download" Version="0.11.4" />
@@ -94,7 +100,7 @@
94100
<PackageReference Include="Xamarin.AndroidX.Annotation" Version="1.8.0.1" />
95101
</ItemGroup>
96102
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
97-
<PackageReference Include="MapboxMapsObjC.iOS" Version="11.5.2.3" />
103+
<PackageReference Include="MapboxMapsObjC.iOS" Version="11.5.2.6" />
98104
<PackageReference Include="MapboxMaps.iOS" Version="11.5.2" />
99105
</ItemGroup>
100106
<ItemGroup>

src/libs/Mapbox.Maui/MapboxView.cs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using MapboxMaui.Annotations;
44
using MapboxMaui.Camera;
5+
using MapboxMaui.Locations;
56
using MapboxMaui.Styles;
67
using MapboxMaui.Viewport;
78

@@ -237,4 +238,5 @@ public MapboxStyle MapboxStyle
237238
public IMapboxController MapboxController { get; internal set; }
238239
public ICameraPlugin CameraController { get; internal set; }
239240
public IViewportPlugin Viewport { get; internal set; }
241+
public ILocationComponentPlugin LocationComponent { get; internal set; }
240242
}

src/libs/Mapbox.Maui/MapboxViewHandler.cs

+6-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public partial class MapboxViewHandler : ViewHandler<IMapboxView, PlatformView>
1414
{
1515
internal static string ACCESS_TOKEN;
1616

17-
public static IPropertyMapper<IMapboxView, MapboxViewHandler> PropertyMapper
17+
public static IPropertyMapper<IMapboxView, MapboxViewHandler> Mapper
1818
= new PropertyMapper<IMapboxView, MapboxViewHandler>(ViewHandler.ViewMapper)
1919
{
2020
[nameof(MapboxView.CameraOptions)] = HandleCameraOptionsChanged,
@@ -28,8 +28,12 @@ public static IPropertyMapper<IMapboxView, MapboxViewHandler> PropertyMapper
2828
[nameof(MapboxView.Terrain)] = HandleTerrainChanged,
2929
[nameof(MapboxView.Light)] = HandleLightChanged
3030
};
31+
public static CommandMapper<IMapboxView, MapboxViewHandler> CommandMapper
32+
= new (ViewHandler.ViewCommandMapper)
33+
{
34+
};
3135

32-
public MapboxViewHandler() : base(PropertyMapper)
36+
public MapboxViewHandler() : base(Mapper, CommandMapper)
3337
{
3438

3539
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace MapboxMaui.Locations;
2+
3+
public interface ILocationComponentPlugin
4+
{
5+
bool Enabled { get; set; }
6+
bool PulsingEnabled { get; set; }
7+
bool ShowAccuracyRing { get; set; }
8+
float PulsingMaxRadius { get; set; }
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
namespace MapboxMaui.Locations;
2+
3+
public interface ILocationPuck { }
4+
5+
public record LocationPuck2D(
6+
/**
7+
* Name of image in sprite to use as the top of the location indicator.
8+
*/
9+
ResolvedImage TopImage = null,
10+
/**
11+
* Name of image in sprite to use as the middle of the location indicator.
12+
*/
13+
ResolvedImage BearingImage = null,
14+
/**
15+
* Name of image in sprite to use as the background of the location indicator.
16+
*/
17+
ResolvedImage ShadowImage = null,
18+
/**
19+
* The scale expression of the images. If defined, it will be applied to all the three images.
20+
*/
21+
string ScaleExpression = null,
22+
/**
23+
* The opacity of the entire location puck
24+
*/
25+
float Opacity = 1f
26+
) : ILocationPuck
27+
{ }
28+
29+
/**
30+
* Definition of a location_puck_3_d.
31+
*/
32+
public record LocationPuck3D(
33+
/**
34+
* An URL for the model file in gltf format.
35+
*/
36+
string ModelUri,
37+
/**
38+
* The position of the model.
39+
*/
40+
float[] Position = default,
41+
/**
42+
* The opacity of the model.
43+
*/
44+
float ModelOpacity = 1f,
45+
/**
46+
* The scale of the model.
47+
*/
48+
float[] ModelScale = default,
49+
/**
50+
* The scale expression of the model, which will overwrite the default scale expression that keeps the model size constant during zoom.
51+
*/
52+
string ModelScaleExpression = null,
53+
/**
54+
* The translation of the model [lon, lat, z]
55+
*/
56+
float[] ModelTranslation = default,
57+
/**
58+
* The rotation of the model.
59+
*/
60+
float[] ModelRotation = default,
61+
/**
62+
* Enable/Disable shadow casting for the 3D location puck.
63+
*/
64+
bool ModelCastShadows = true,
65+
/**
66+
* Enable/Disable shadow receiving for the 3D location puck.
67+
*/
68+
bool ModelReceiveShadows = true,
69+
/**
70+
* Defines scaling mode. Only applies to location-indicator type layers.
71+
*/
72+
ModelScaleMode modelScaleMode = ModelScaleMode.Viewport,
73+
/**
74+
* Strength of the emission. There is no emission for value 0. For value 1.0, only emissive component (no shading) is displayed and values above 1.0 produce light contribution to surrounding area, for some of the parts (e.g. doors).
75+
*/
76+
float modelEmissiveStrength = 1f,
77+
/**
78+
* Strength of the emission as Expression string, note that when [modelEmissiveStrengthExpression] is specified, it will overwrite the [modelEmissiveStrength] property. There is no emission for value 0. For value 1.0, only emissive component (no shading) is displayed and values above 1.0 produce light contribution to surrounding area, for some of the parts (e.g. doors).
79+
*/
80+
string modelEmissiveStrengthExpression = default
81+
) : ILocationPuck
82+
{
83+
public float[] Position { get; init; } = Position ?? [0, 0];
84+
public float[] ModelScale { get; init; } = ModelScale ?? [1, 1, 1];
85+
public float[] ModelTranslation { get; init; } = ModelTranslation ?? [0, 0, 0];
86+
public float[] ModelRotation { get; init; } = ModelRotation ?? [0, 0, 90];
87+
}
88+
89+
/**
90+
* Defines scaling mode. Only applies to location-indicator type layers.
91+
*
92+
* @param value String value of this property
93+
*/
94+
public enum ModelScaleMode
95+
{
96+
/**
97+
* Model is scaled so that it's always the same size relative to other map features. The property model-scale specifies how many meters each unit in the model file should cover.
98+
*/
99+
Map,
100+
/**
101+
* Model is scaled so that it's always the same size on the screen. The property model-scale specifies how many pixels each unit in model file should cover.
102+
*/
103+
Viewport,
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using Microsoft.VisualBasic;
2+
3+
namespace MapboxMaui.Locations;
4+
5+
/**
6+
* Shows a location puck on the map.
7+
*/
8+
public record LocationComponentSettings(
9+
/**
10+
* Whether the user location is visible on the map.
11+
*/
12+
bool Enabled,
13+
/**
14+
* Whether the location puck is pulsing on the map. Works for 2D location puck only.
15+
*/
16+
bool PulsingEnabled,
17+
/**
18+
* The color of the pulsing circle. Works for 2D location puck only.
19+
*/
20+
int PulsingColor,
21+
/**
22+
* The maximum radius of the pulsing circle. Works for 2D location puck only. Note: Setting
23+
* [pulsingMaxRadius] to LocationComponentConstants.PULSING_MAX_RADIUS_FOLLOW_ACCURACY will set the
24+
* pulsing circle's maximum radius to follow location accuracy circle. This property is specified in
25+
* pixels.
26+
*/
27+
float PulsingMaxRadius,
28+
/**
29+
* Whether show accuracy ring with location puck. Works for 2D location puck only.
30+
*/
31+
bool ShowAccuracyRing,
32+
/**
33+
* The color of the accuracy ring. Works for 2D location puck only.
34+
*/
35+
int AccuracyRingColor,
36+
/**
37+
* The color of the accuracy ring border. Works for 2D location puck only.
38+
*/
39+
int AccuracyRingBorderColor,
40+
/**
41+
* Sets the id of the layer that's added above to when placing the component on the map.
42+
*/
43+
string LayerAbove,
44+
/**
45+
* Sets the id of the layer that's added below to when placing the component on the map.
46+
*/
47+
string LayerBelow,
48+
/**
49+
* Whether the puck rotates to track the bearing source.
50+
*/
51+
bool PuckBearingEnabled,
52+
/**
53+
* The enum controls how the puck is oriented
54+
*/
55+
PuckBearing puckBearing,
56+
/**
57+
* The slot this layer is assigned to. If specified, and a slot with that name exists, it will be
58+
* placed at that position in the layer order.
59+
*/
60+
string Slot,
61+
/**
62+
* Defines what the customised look of the location puck. Note that direct changes to the puck
63+
* variables won't have any effect, a new puck needs to be set every time.
64+
*/
65+
ILocationPuck LocationPuck
66+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace MapboxMaui.Locations;
2+
3+
public enum PuckBearing
4+
{
5+
Heading,
6+
Course,
7+
}

src/libs/Mapbox.Maui/Platforms/Android/MapboxFragment.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public partial class MapboxFragment : Fragment
2525
public event Action<MapView> MapLoaded;
2626
public event Action<MapView> MapLoadingError;
2727
public event Action<MapTappedPosition> MapLongClicked;
28+
public event Action<MapView> MapReady;
2829
public event Action<MapView> StyleLoaded;
2930
public event Action<ViewportStatusChangedEventArgs> ViewportStatusChanged;
3031
public event Action<RotatingEventArgs> Rotating;
@@ -57,7 +58,10 @@ public override View OnCreateView(LayoutInflater inflater, ViewGroup container,
5758
MapboxOptions.AccessToken = MapboxViewHandler.ACCESS_TOKEN;
5859
}
5960

60-
return MapView = new MapView(Context);
61+
MapView = new MapView(Context);
62+
63+
MapReady?.Invoke(MapView);
64+
return MapView;
6165
}
6266

6367
public override void OnViewCreated(View view, Bundle savedInstanceState)

src/libs/Mapbox.Maui/Platforms/Android/MapboxViewHandler.Camera.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Android.Animation;
2+
using Android.App;
3+
using Com.Mapbox.Functions;
24
using Com.Mapbox.Maps.Plugins.Animation;
35
using MapboxMaui.Camera;
46

@@ -12,7 +14,7 @@ public CameraOptions CameraState
1214
{
1315
var mapView = mapboxFragment?.MapView;
1416

15-
if (mapView == null) return default;
17+
if (mapView is null) return default;
1618

1719
return mapView.MapboxMap.CameraState.ToX();
1820
}
@@ -22,7 +24,7 @@ public void EaseTo(CameraOptions cameraOptions, AnimationOptions animationOption
2224
{
2325
var mapView = mapboxFragment?.MapView;
2426

25-
if (mapView == null) return;
27+
if (mapView is null) return;
2628

2729
var xcameraOptions = cameraOptions.ToNative();
2830
var xanimationOptions = animationOptions?.ToNative();
@@ -41,7 +43,7 @@ public void FlyTo(CameraOptions cameraOptions, AnimationOptions animationOptions
4143
{
4244
var mapView = mapboxFragment?.MapView;
4345

44-
if (mapView == null) return;
46+
if (mapView is null) return;
4547

4648
var xcameraOptions = cameraOptions.ToNative();
4749
var xanimationOptions = animationOptions?.ToNative();

0 commit comments

Comments
 (0)