Skip to content

Commit

Permalink
finish iOS location indicator impl
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianBissekkou committed Nov 28, 2023
1 parent c0a6e9b commit df29f97
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 20 deletions.
42 changes: 31 additions & 11 deletions arcgis_map_sdk/lib/src/arcgis_location_display.dart
Original file line number Diff line number Diff line change
@@ -1,55 +1,75 @@
import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart';
import 'package:flutter/cupertino.dart';

class ArcgisManualLocationDisplay extends ArcgisLocationDisplay {
@override
String get type => "manual";

ArcgisManualLocationDisplay(super.mapId);
ArcgisManualLocationDisplay({super.mapId});

Future<void> updateLocation(UserPosition position) {
_assertAttached();
return ArcgisMapPlatform.instance
.updateLocationDisplaySourcePositionManually(
mapId,
_mapId!,
position,
);
}
}

class ArcgisLocationDisplay {
final int mapId;
int? _mapId;
final String type = "system";

ArcgisLocationDisplay(this.mapId);
ArcgisLocationDisplay({int? mapId}) : _mapId = mapId;

void attachToMap(int mapId) => _mapId = mapId;

void deattachFromMap() => _mapId = null;

Future<void> startSource() {
return ArcgisMapPlatform.instance.startLocationDisplayDataSource(mapId);
_assertAttached();
return ArcgisMapPlatform.instance.startLocationDisplayDataSource(_mapId!);
}

Future<void> stopSource() {
return ArcgisMapPlatform.instance.stopLocationDisplayDataSource(mapId);
_assertAttached();
return ArcgisMapPlatform.instance.stopLocationDisplayDataSource(_mapId!);
}

Future<void> setDataSource() {
return ArcgisMapPlatform.instance.setLocationDisplayDataSource(mapId);
_assertAttached();
return ArcgisMapPlatform.instance.setLocationDisplayDataSource(_mapId!);
}

Future<void> setDefaultSymbol(Symbol symbol) {
_assertAttached();
return ArcgisMapPlatform.instance
.setLocationDisplayDefaultSymbol(mapId, symbol);
.setLocationDisplayDefaultSymbol(_mapId!, symbol);
}

Future<void> setAccuracySymbol(Symbol symbol) {
_assertAttached();
return ArcgisMapPlatform.instance
.setLocationDisplayAccuracySymbol(mapId, symbol);
.setLocationDisplayAccuracySymbol(_mapId!, symbol);
}

Future<void> setPingAnimationSymbol(Symbol symbol) {
_assertAttached();
return ArcgisMapPlatform.instance
.setLocationDisplayPingAnimationSymbol(mapId, symbol);
.setLocationDisplayPingAnimationSymbol(_mapId!, symbol);
}

Future<void> setUseCourseSymbolOnMovement(bool useCourseSymbol) {
_assertAttached();
return ArcgisMapPlatform.instance
.setUseCourseSymbolOnMovement(mapId, useCourseSymbol);
.setUseCourseSymbolOnMovement(_mapId!, useCourseSymbol);
}

void _assertAttached() {
assert(
_mapId != null,
"LocationDisplay has not been attached to any map. Make sure to call ArcgisMapController.setLocationDisplay.",
);
}
}
9 changes: 7 additions & 2 deletions arcgis_map_sdk/lib/src/arcgis_map_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:flutter/services.dart';
class ArcgisMapController {
ArcgisMapController._({
required this.mapId,
}) : _locationDisplay = ArcgisLocationDisplay(mapId);
}) : _locationDisplay = ArcgisLocationDisplay(mapId: mapId);

final int mapId;

Expand Down Expand Up @@ -258,6 +258,11 @@ class ArcgisMapController {
Future<void> setLocationDisplay(ArcgisLocationDisplay locationDisplay) {
return ArcgisMapPlatform.instance
.setLocationDisplay(mapId, locationDisplay.type)
.whenComplete(() => _locationDisplay = locationDisplay);
.whenComplete(
() {
_locationDisplay.deattachFromMap();
_locationDisplay = locationDisplay..attachToMap(mapId);
},
);
}
}
3 changes: 2 additions & 1 deletion arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
return
}

source.setNewLocation(coordinate: position.latLng, accuracy: position.accuracy, course: position.heading)
source.setNewLocation(position)
result(true)
}

private func onSetLocationDisplayDataSourceType(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
Expand Down
10 changes: 5 additions & 5 deletions arcgis_map_sdk_ios/ios/Classes/ManualLocationDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import Foundation
import ArcGIS

class ManualLocationDataSource: AGSLocationDataSource {
public func setNewLocation(coordinate: LatLng, accuracy: Double?, course: Double?) {
public func setNewLocation(_ position: UserPosition) {
let loc = AGSLocation(
position: coordinate.toAGSPoint(),
horizontalAccuracy: accuracy ?? 0,
velocity: 0,
course: course ?? 0,
position: position.latLng.toAGSPoint(),
horizontalAccuracy: position.accuracy ?? 0,
velocity: position.velocity ?? 0,
course: position.heading ?? 0,
lastKnown: false
)
didUpdate(loc)
Expand Down
1 change: 1 addition & 0 deletions arcgis_map_sdk_ios/ios/Classes/Models/UserPosition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ struct UserPosition: Codable {
let latLng: LatLng
let accuracy: Double?
let heading: Double?
let velocity: Double?
}
1 change: 1 addition & 0 deletions arcgis_map_sdk_method_channel/lib/src/model_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extension UserPositionExtension on UserPosition {
'latLng': latLng.toMap(),
'accuracy': accuracy,
'heading': heading,
'velocity': velocity,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ class UserPosition {
final LatLng latLng;
final double? accuracy;
final double? heading;
final double? velocity;

const UserPosition({
required this.latLng,
required this.accuracy,
this.accuracy,
this.velocity,
this.heading,
});
}
64 changes: 64 additions & 0 deletions example/lib/location_indicator_example_page.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:math';

import 'package:arcgis_example/main.dart';
import 'package:arcgis_map_sdk/arcgis_map_sdk.dart';
import 'package:flutter/material.dart';
Expand All @@ -13,10 +15,21 @@ class LocationIndicatorExamplePage extends StatefulWidget {

class _LocationIndicatorExamplePageState
extends State<LocationIndicatorExamplePage> {
final _mockLocations = [
LatLng(48.1234963, 11.5910182),
LatLng(48.1239241, 11.45897063),
LatLng(48.123876, 11.590120),
LatLng(48.123876, 11.590120),
LatLng(48.123740, 11.589015),
LatLng(48.123164, 11.588585),
LatLng(48.1234963, 11.5910182),
];

final _snackBarKey = GlobalKey<ScaffoldState>();
ArcgisMapController? _controller;
bool _isStarted = false;
bool _useCourseSymbolForMovement = false;
bool _isManualLocationSource = false;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -59,6 +72,20 @@ class _LocationIndicatorExamplePageState
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _switchLocationSource,
child: Text(
_isManualLocationSource
? "Use auto location source"
: "Use manual location source",
),
),
if (_isManualLocationSource) ...[
ElevatedButton(
onPressed: _simulateLocationChange,
child: Text("simulate location change"),
),
],
ElevatedButton(
onPressed: () => _configureLocationDisplay(Colors.green),
child: Text("tint indicator green"),
Expand Down Expand Up @@ -120,4 +147,41 @@ class _LocationIndicatorExamplePageState
SimpleLineSymbol(color: color.shade800, width: 3),
);
}

Future<void> _switchLocationSource() async {
await _controller!.locationDisplay.stopSource();
await _controller!.setLocationDisplay(
_isManualLocationSource
? ArcgisLocationDisplay()
: ArcgisManualLocationDisplay(),
);
setState(() => _isManualLocationSource = !_isManualLocationSource);

if (!_isManualLocationSource) {
final location = await Geolocator.getLastKnownPosition();
if (location == null) return;
await _controller!.moveCamera(
point: LatLng(location.latitude, location.longitude),
);
}
}

Future<void> _simulateLocationChange() async {
final display = _controller!.locationDisplay as ArcgisManualLocationDisplay;

await _controller!.moveCamera(point: _mockLocations.first);
for (final latLng in _mockLocations) {
if (!mounted) break;
if (!_isManualLocationSource) break;

await display.updateLocation(
UserPosition(
latLng: latLng,
accuracy: Random().nextInt(100).toDouble(),
velocity: Random().nextInt(100).toDouble(),
),
);
await Future<void>.delayed(const Duration(milliseconds: 600));
}
}
}

0 comments on commit df29f97

Please sign in to comment.