3
import 'package:flutter/foundation.dart';
4
import 'package:flutter/material.dart';
5
import 'package:flutter/services.dart';
6
import 'package:fluttertoast/fluttertoast.dart';
7
import 'package:nb_navigation_flutter/nb_navigation_flutter.dart';
8
import 'package:nb_navigation_flutter_example/constants.dart';
10
class FullNavigationExample extends StatefulWidget {
11
static const String title = "Full Navigation Experience Example";
13
const FullNavigationExample({super.key});
16
FullNavigationExampleState createState() => FullNavigationExampleState();
19
class FullNavigationExampleState extends State<FullNavigationExample> {
20
NextbillionMapController? controller;
21
List<DirectionsRoute> routes = [];
22
late NavNextBillionMap navNextBillionMap;
23
Symbol? mapMarkerSymbol;
25
String locationTrackImage = "assets/location_on.png";
26
UserLocation? currentLocation;
27
List<LatLng> waypoints = [];
29
void _onMapCreated(NextbillionMapController controller) {
30
this.controller = controller;
33
_onStyleLoadedCallback() {
34
if (controller != null) {
35
NavNextBillionMap.create(controller!).then((value) {
36
navNextBillionMap = value;
38
Fluttertoast.showToast(
39
msg: "Long press to select a destination to fetch a route");
40
if (currentLocation != null) {
41
controller?.animateCamera(
42
CameraUpdate.newLatLngZoom(currentLocation!.position, 14),
43
duration: const Duration(milliseconds: 400));
49
_onMapLongClick(Point<double> point, LatLng coordinates) {
50
_fetchRoute(coordinates);
53
_onMapClick(Point<double> point, LatLng coordinates) {
54
navNextBillionMap.addRouteSelectedListener(coordinates,
55
(selectedRouteIndex) {
56
if (routes.isNotEmpty && selectedRouteIndex != 0) {
57
var selectedRoute = routes[selectedRouteIndex];
58
routes.removeAt(selectedRouteIndex);
59
routes.insert(0, selectedRoute);
63
navNextBillionMap.drawRoute(routes);
68
_onUserLocationUpdate(UserLocation location) {
69
currentLocation = location;
72
_onCameraTrackingChanged() {
74
locationTrackImage = 'assets/location_off.png';
79
Widget build(BuildContext context) {
83
onMapCreated: _onMapCreated,
84
onStyleLoadedCallback: _onStyleLoadedCallback,
85
initialCameraPosition: const CameraPosition(
89
trackCameraPosition: true,
90
myLocationEnabled: true,
91
myLocationTrackingMode: MyLocationTrackingMode.Tracking,
92
onMapLongClick: _onMapLongClick,
93
onUserLocationUpdated: _onUserLocationUpdate,
94
onCameraTrackingDismissed: _onCameraTrackingChanged,
95
onMapClick: _onMapClick,
96
styleString: NbNavigationStyles.nbMapDefaultLightStyle,
99
padding: const EdgeInsets.all(8.0),
101
mainAxisAlignment: MainAxisAlignment.end,
102
crossAxisAlignment: CrossAxisAlignment.start,
105
padding: const EdgeInsets.all(8.0),
106
child: GestureDetector(
108
image: AssetImage(locationTrackImage),
113
controller?.updateMyLocationTrackingMode(
114
MyLocationTrackingMode.Tracking);
116
locationTrackImage = 'assets/location_on.png';
120
const Padding(padding: EdgeInsets.only(top: 35)),
122
mainAxisAlignment: MainAxisAlignment.center,
126
backgroundColor: WidgetStateProperty.all(
127
routes.isEmpty ? Colors.grey : Colors.blueAccent),
128
enableFeedback: routes.isNotEmpty),
133
child: const Text("Clear Routes")),
134
const Padding(padding: EdgeInsets.only(left: 8)),
137
backgroundColor: WidgetStateProperty.all(
138
routes.isEmpty ? Colors.grey : Colors.blueAccent),
139
enableFeedback: routes.isNotEmpty),
143
child: const Text("Start Navigation")),
146
const Padding(padding: EdgeInsets.only(top: 48)),
148
// padding: const EdgeInsets.only(top: 8.0),
149
// child: Text("route response: ${routeResult}"),
158
void _fetchRoute(LatLng destination) async {
159
if (currentLocation == null) {
162
LatLng origin = currentLocation!.position;
163
waypoints.add(destination);
164
RouteRequestParams requestParams = RouteRequestParams(
166
destination: waypoints.last,
167
// overview: ValidOverview.simplified,
168
// avoid: [SupportedAvoid.toll, SupportedAvoid.ferry],
169
// option: SupportedOption.flexible,
170
// truckSize: [200, 200, 600],
172
// unit: SupportedUnits.imperial,
174
mode: ValidModes.car,
177
if (waypoints.length > 1) {
178
requestParams.waypoints = waypoints.sublist(0, waypoints.length - 1);
181
DirectionsRouteResponse routeResponse =
182
await NBNavigation.fetchRoute(requestParams);
183
if (routeResponse.directionsRoutes.isNotEmpty) {
186
routes = routeResponse.directionsRoutes;
189
fitCameraToBounds(routes);
190
addImageFromAsset(destination);
191
} else if (routeResponse.message != null) {
194
"====error====${routeResponse.message}===${routeResponse.errorCode}");
199
Future<void> drawRoutes(List<DirectionsRoute> routes) async {
200
// navNextBillionMap.toggleDurationSymbolVisibilityWith(false);
201
navNextBillionMap.drawRoute(routes);
204
void fitCameraToBounds(List<DirectionsRoute> routes) {
205
List<LatLng> multiPoints = [];
206
for (var route in routes) {
208
decode(route.geometry ?? '', _getDecodePrecision(route.routeOptions));
209
multiPoints.addAll(routePoints);
211
if (multiPoints.isNotEmpty) {
212
var latLngBounds = LatLngBounds.fromMultiLatLng(multiPoints);
213
controller?.animateCamera(CameraUpdate.newLatLngBounds(latLngBounds,
214
top: 50, left: 50, right: 50, bottom: 50));
218
int _getDecodePrecision(RouteRequestParams? routeOptions) {
219
return routeOptions?.geometry == SupportedGeometry.polyline
224
void clearRouteResult() async {
225
navNextBillionMap.clearRoute();
226
controller?.clearSymbols();
232
void _startNavigation() {
233
if (routes.isEmpty) return;
234
NavigationLauncherConfig config =
235
NavigationLauncherConfig(route: routes.first, routes: routes);
236
config.locationLayerRenderMode = LocationLayerRenderMode.gps;
237
config.shouldSimulateRoute = false;
238
config.themeMode = NavigationThemeMode.system;
239
config.useCustomNavigationStyle = false;
240
NBNavigation.startNavigation(config);
243
Future<void> loadAssetImage() async {
244
final ByteData bytes = await rootBundle.load("assets/map_marker_light.png");
245
final Uint8List list = bytes.buffer.asUint8List();
246
await controller?.addImage("ic_marker_destination", list);
249
Future<void> addImageFromAsset(LatLng coordinates) async {
250
controller?.clearSymbols();
251
var symbolOptions = SymbolOptions(
252
geometry: coordinates,
253
iconImage: "ic_marker_destination",
255
await controller?.addSymbol(symbolOptions);
256
controller?.symbolManager?.setTextAllowOverlap(false);
266
// TODO: implement dispose
271
void didUpdateWidget(FullNavigationExample oldWidget) {
272
// TODO: implement didUpdateWidget
273
super.didUpdateWidget(oldWidget);
277
void didChangeDependencies() {
278
// TODO: implement didChangeDependencies
279
super.didChangeDependencies();