Skip to content

Commit 1838c7a

Browse files
authored
- Example for using camera fly animation (#16)
1 parent fc1816b commit 1838c7a

17 files changed

+246
-9
lines changed

build.cake

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
var target = Argument("target", "example");
44
var name = Argument("name", "Awesome");
55
var index = Argument("index", 0);
6+
var gindex = Argument("gindex", 0);
67
var group = Argument("group", "None");
78
var title = Argument("title", "Awesome");
89
var subtitle = Argument("subtitle", "Awesome");
@@ -36,6 +37,8 @@ class {name}ExampleInfo : IExampleInfo
3637
public string Title => ""{title ?? "No title"}"";
3738
public string Subtitle => ""{subtitle ?? "No subtitle"}"";
3839
public string PageRoute => typeof({name}Example).FullName;
40+
public int GroupIndex => {gindex};
41+
public int Index => {index};
3942
}}");
4043

4144
Information($"\n>> Generate >> {name}ExamplePage.cs");
@@ -64,7 +67,7 @@ public class {name}Example : ContentPage, IExamplePage, IQueryAttributable
6467
6568
private void Map_MapReady(object sender, EventArgs e)
6669
{{
67-
var centerLocation = new Point(21.0278, 105.8342);
70+
var centerLocation = new MapPosition(21.0278, 105.8342);
6871
var cameraOptions = new CameraOptions
6972
{{
7073
Center = centerLocation,

src/libs/Mapbox.Maui/IMapboxView.cs

+5
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public interface IMapboxController
6767
CoordinateBounds GetCoordinateBoundsForCamera(CameraOptions cameraOptions);
6868
}
6969

70+
public interface IMapCameraController
71+
{
72+
void FlyTo(CameraOptions cameraOptions, AnimationOptions animationOptions = default, Action<AnimationState> completion = default);
73+
}
74+
7075
public class MapTappedEventArgs : EventArgs
7176
{
7277
public MapTappedPosition Position { get; }

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

+6-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
<RepositoryUrl>https://github.com/tuyen-vuduc/mapbox-maui</RepositoryUrl>
5454
<PackageProjectUrl>https://mapbox.tuyen-vuduc.tech</PackageProjectUrl>
5555
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
56-
<PackageVersion>11.3.0-alpha03</PackageVersion>
56+
<PackageVersion>11.3.0-alpha04</PackageVersion>
5757
<PackageReadmeFile>README.md</PackageReadmeFile>
5858
<PackageLicenseFile>LICENSE</PackageLicenseFile>
5959
<PackageIcon>tv-mapbox.png</PackageIcon>
@@ -104,6 +104,11 @@
104104
</Properties>
105105
</MonoDevelop>
106106
</ProjectExtensions>
107+
<ItemGroup>
108+
<Compile Update="Platforms\Android\MapboxViewHandler.Camera.cs">
109+
<ExcludeFromCurrentConfiguration>true</ExcludeFromCurrentConfiguration>
110+
</Compile>
111+
</ItemGroup>
107112
<ItemGroup>
108113
<PackageReference Update="Microsoft.Maui.Controls.Compatibility" Version="8.0.40" />
109114
</ItemGroup>

src/libs/Mapbox.Maui/MapboxView.cs

+1
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,5 @@ public MapboxStyle MapboxStyle
222222
public IAnnotationController AnnotationController { get; internal set; }
223223
public IMapFeatureQueryable QueryManager { get; internal set; }
224224
public IMapboxController MapboxController { get; internal set; }
225+
public IMapCameraController CameraController { get; internal set; }
225226
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace MapboxMaui;
2+
3+
public record AnimationOptions (
4+
long? Duration,
5+
TimingCurve Curve = TimingCurve.EaseOut,
6+
long? StartDelay = default,
7+
string Owner = default);
8+
9+
public enum TimingCurve
10+
{
11+
EaseIn,
12+
EaseInOut,
13+
EaseOut,
14+
Linear,
15+
}
16+
17+
public enum AnimatingPosition
18+
{
19+
End,
20+
Start,
21+
Current
22+
}
23+
24+
public record AnimationState(AnimatingPosition Position);

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

+24
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,35 @@
1313
using System.Collections;
1414
using MapboxMaui.Expressions;
1515
using AndroidX.Fragment.App;
16+
using Com.Mapbox.Maps.Plugins.Animation;
17+
using Com.Mapbox.Functions;
1618

1719
static class AdditionalExtensions
1820
{
1921
internal static DisplayMetrics Metrics;
2022

23+
public static MapAnimationOptions ToNative(this AnimationOptions animationOptions)
24+
{
25+
return MapAnimationOptions.CompanionField.MapAnimationOptions(
26+
new Function1Action<MapAnimationOptions.Builder>((builder) =>
27+
{
28+
if (animationOptions.Duration.HasValue)
29+
{
30+
builder.Duration(animationOptions.Duration.Value);
31+
}
32+
if (animationOptions.StartDelay.HasValue)
33+
{
34+
builder.StartDelay(animationOptions.StartDelay.Value);
35+
}
36+
if (!string.IsNullOrWhiteSpace(animationOptions.Owner))
37+
{
38+
builder.Owner(animationOptions.Owner);
39+
}
40+
41+
// TODO Set curve options
42+
}));
43+
}
44+
2145
internal static double PixelToPoint(this double pixel)
2246
{
2347
Metrics ??= Resources.System?.DisplayMetrics;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Android.Animation;
2+
using Com.Mapbox.Maps.Plugins.Animation;
3+
4+
namespace MapboxMaui;
5+
6+
partial class MapboxViewHandler : IMapCameraController
7+
{
8+
public void FlyTo(CameraOptions cameraOptions, AnimationOptions animationOptions = default, Action<AnimationState> completion = default)
9+
{
10+
var mapView = mapboxFragment?.MapView;
11+
12+
if (mapView == null) return;
13+
14+
var xcameraOptions = cameraOptions.ToNative();
15+
var xanimationOptions = animationOptions?.ToNative();
16+
17+
// TODO Return Cancellable obj
18+
CameraAnimationsUtils.FlyTo(
19+
mapView.MapboxMap,
20+
xcameraOptions,
21+
xanimationOptions,
22+
completion != null
23+
? new XAnimationListener(completion)
24+
: null);
25+
}
26+
27+
private class XAnimationListener : Java.Lang.Object, Android.Animation.Animator.IAnimatorListener
28+
{
29+
private Action<AnimationState> completion;
30+
31+
public XAnimationListener(Action<AnimationState> completion)
32+
{
33+
this.completion = completion;
34+
}
35+
36+
public void OnAnimationCancel(Animator animation)
37+
{
38+
}
39+
40+
public void OnAnimationEnd(Animator animation)
41+
{
42+
completion(new AnimationState(AnimatingPosition.End));
43+
}
44+
45+
public void OnAnimationRepeat(Animator animation)
46+
{
47+
}
48+
49+
public void OnAnimationStart(Animator animation)
50+
{
51+
completion(new AnimationState(AnimatingPosition.Start));
52+
}
53+
}
54+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
23
namespace MapboxMaui;
34

45
partial class MapboxViewHandler : IMapboxController

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

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ protected override void ConnectHandler(PlatformView platformView)
230230
mapboxView.AnnotationController = this;
231231
mapboxView.QueryManager = this;
232232
mapboxView.MapboxController = this;
233+
mapboxView.CameraController = this;
233234
}
234235
}
235236

@@ -250,6 +251,8 @@ protected override void DisconnectHandler(PlatformView platformView)
250251
{
251252
mapboxView.AnnotationController = null;
252253
mapboxView.QueryManager = null;
254+
mapboxView.CameraController = null;
255+
mapboxView.MapboxController = null;
253256
}
254257
base.DisconnectHandler(platformView);
255258
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using MapboxMapsObjC;
2+
3+
namespace MapboxMaui;
4+
5+
partial class MapboxViewHandler : IMapCameraController
6+
{
7+
public void FlyTo(CameraOptions cameraOptions, AnimationOptions animationOptions = default, Action<AnimationState> completion = default)
8+
{
9+
var mapView = PlatformView.MapView;
10+
11+
if (mapView == null) return;
12+
13+
var xcameraOptions = cameraOptions.ToNative();
14+
mapView.Camera().FlyTo(
15+
xcameraOptions,
16+
animationOptions?.Duration / 1000L ?? 0,
17+
(position) =>
18+
{
19+
var xposition = position switch
20+
{
21+
UIKit.UIViewAnimatingPosition.Start => AnimatingPosition.Start,
22+
UIKit.UIViewAnimatingPosition.End => AnimatingPosition.End,
23+
UIKit.UIViewAnimatingPosition.Current => AnimatingPosition.Current,
24+
_ => AnimatingPosition.Current,
25+
};
26+
27+
completion?.Invoke(new AnimationState(xposition));
28+
});
29+
}
30+
}

src/libs/Mapbox.Maui/Platforms/iOS/MapboxViewHandler.cs

+2
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ protected override void DisconnectHandler(PlatformView platformView)
287287
mapboxView.AnnotationController = null;
288288
mapboxView.QueryManager = null;
289289
mapboxView.MapboxController = null;
290+
mapboxView.CameraController = null;
290291
}
291292

292293
var mapView = platformView.MapView;
@@ -313,6 +314,7 @@ protected override void ConnectHandler(PlatformView platformView)
313314
mapboxView.AnnotationController = this;
314315
mapboxView.QueryManager = this;
315316
mapboxView.MapboxController = this;
317+
mapboxView.CameraController = this;
316318
}
317319

318320
var mapView = platformView.MapView;

src/qs/MapboxMauiQs/Examples/41.OfflineManager/OfflineManagerExample.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ private void Map_MapReady(object sender, EventArgs e)
2929
map.MapboxStyle = MapboxStyle.OUTDOORS;
3030

3131
offlineManager = new OfflineManager(
32-
MauiProgram.AccessToken,
32+
MauiProgram.ACCESS_TOKEN,
3333
cameraOptions);
3434

3535
offlineManager.IsMapboxStackConnected = true;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
namespace MapboxMauiQs;
2+
3+
public class CameraFlyAnimationExample : ContentPage, IExamplePage, IQueryAttributable
4+
{
5+
MapboxView map;
6+
IExampleInfo info;
7+
8+
public CameraFlyAnimationExample()
9+
{
10+
iOSPage.SetUseSafeArea(this, false);
11+
12+
var grid = new Grid();
13+
map = new MapboxView();
14+
grid.Children.Add(map);
15+
16+
var btnMoveCamera = new Button()
17+
{
18+
Text = "Move Camera",
19+
VerticalOptions = LayoutOptions.End,
20+
HorizontalOptions = LayoutOptions.Center,
21+
Margin = new Thickness(24),
22+
};
23+
btnMoveCamera.Clicked += HandleMoveCamera;
24+
grid.Children.Add(btnMoveCamera);
25+
26+
map.MapReady += Map_MapReady;
27+
map.StyleLoaded += Map_StyleLoaded;
28+
map.MapLoaded += Map_MapLoaded;
29+
30+
Content = grid;
31+
}
32+
33+
private void HandleMoveCamera(object sender, EventArgs e)
34+
{
35+
var centerLocation = new MapPosition(21.0278, 105.8342);
36+
var cameraOptions = new CameraOptions
37+
{
38+
Center = centerLocation,
39+
Zoom = 9,
40+
};
41+
map.CameraController.FlyTo(
42+
cameraOptions,
43+
new AnimationOptions(3000L));
44+
}
45+
46+
public void ApplyQueryAttributes(IDictionary<string, object> query)
47+
{
48+
info = query["example"] as IExampleInfo;
49+
50+
Title = info?.Title;
51+
}
52+
53+
private void Map_MapReady(object sender, EventArgs e)
54+
{
55+
var centerLocation = new MapPosition(60.1699, 24.9384);
56+
var cameraOptions = new CameraOptions
57+
{
58+
Center = centerLocation,
59+
Zoom = 9,
60+
};
61+
map.CameraOptions = cameraOptions;
62+
map.MapboxStyle = MapboxStyle.STANDARD;
63+
}
64+
65+
private void Map_MapLoaded(object sender, EventArgs e)
66+
{
67+
// Setup Styles, Annotations, etc here
68+
}
69+
private void Map_StyleLoaded(object sender, EventArgs e)
70+
{
71+
}
72+
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace MapboxMauiQs;
2+
3+
class CameraFlyAnimationExampleInfo : IExampleInfo
4+
{
5+
public string Group => "Lab";
6+
public string Title => "Camera Fly Animation";
7+
public string Subtitle => "Change mapcenter with fly animation";
8+
public string PageRoute => typeof(CameraFlyAnimationExample).FullName;
9+
public int GroupIndex => 0;
10+
public int Index => 65;
11+
}

src/qs/MapboxMauiQs/MapboxMauiQs.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@
119119
<CodesignKey>Apple Development: Created via API (X3MP9CYJPQ)</CodesignKey>
120120
<CodesignProvision>VS: WildCard Development</CodesignProvision>
121121
</PropertyGroup>
122+
<PropertyGroup Condition="'$(TargetFramework)'=='net8.0-ios'">
123+
<CodesignKey>Apple Development: Created via API (X3MP9CYJPQ)</CodesignKey>
124+
<CodesignProvision>VS: WildCard Development</CodesignProvision>
125+
</PropertyGroup>
122126
<Target Name="DisplayMessages" BeforeTargets="PrepareForILLink">
123127
<Message Text="Project File Name = $(Configuration)|$(TargetFramework)|$(Platform)" />
124128
</Target>

src/qs/MapboxMauiQs/MauiProgram.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,12 @@ namespace MapboxMauiQs;
55

66
public static partial class MauiProgram
77
{
8-
public static string AccessToken => throw new Exception("[your token]");
9-
108
public static MauiApp CreateMauiApp()
119
{
1210
var builder = MauiApp.CreateBuilder();
1311
builder
1412
.UseMauiApp<App>()
15-
.UseMapbox(AccessToken)
13+
.UseMapbox(ACCESS_TOKEN)
1614
.ConfigureFonts(fonts =>
1715
{
1816
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="tech.tuyen-vuduc.mapboxmauiqs" android:versionCode="1" android:versionName="1.0">
3-
<application android:allowBackup="true" android:supportsRtl="true" android:label="MapboxQs" android:icon="@mipmap/appicon"></application>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0">
3+
<application android:allowBackup="true" android:supportsRtl="true" android:icon="@mipmap/appicon"></application>
44
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
55
<uses-permission android:name="android.permission.INTERNET" />
6-
<uses-sdk android:minSdkVersion="27" android:targetSdkVersion="34" />
76
</manifest>

0 commit comments

Comments
 (0)