Route Creation Example
This example demonstrates how to create routes with flexible origin handling and fallback logic.
Route Creation Features
The Lazarillo Maps plugin provides enhanced route creation with the following features:
Flexible Origin Handling
// Create route with specific origin
final route = await lazarilloMaps.addRoute(
RouteConfiguration(
mapId: 'map-id',
initialLocation: originPlace.position, // Specific origin
finalLocation: destinationPlace.position,
),
);
// Create route with current location as fallback
final route = await lazarilloMaps.addRoute(
RouteConfiguration(
mapId: 'map-id',
finalLocation: destinationPlace.position, // No origin specified
),
);Route Configuration
final config = RouteConfiguration(
mapId: 'map-id',
initialLocation: originPlace.position, // Optional
finalLocation: destinationPlace.position, // Required
nextStepsRouteColor: '#FF0000', // Custom colors
prevStepsRouteColor: '#CCCCCC',
polylineWidth: 10.0,
language: 'es',
unitSystem: 'METRIC',
);Complete Example
Here’s a complete example showing route creation with origin selection:
import 'package:flutter/material.dart';
import 'package:lazarillo_maps/lazarillo_maps.dart';
class RouteCreationExample extends StatefulWidget {
const RouteCreationExample({super.key});
@override
State<RouteCreationExample> createState() => _RouteCreationExampleState();
}
class _RouteCreationExampleState extends State<RouteCreationExample> {
final LazarilloMaps _lazarilloMaps = LazarilloMaps('your-api-key');
List<LzPlace> _places = [];
LzPlace? _selectedOrigin;
LzPlace? _selectedDestination;
LzRoute? _currentRoute;
bool _isLoading = false;
@override
void initState() {
super.initState();
_initializeMap();
}
Future<void> _initializeMap() async {
await _lazarilloMaps.initialize();
await _loadPlaces();
}
Future<void> _loadPlaces() async {
setState(() {
_isLoading = true;
});
try {
// Use getPlacesForApiKey to fetch available places
final places = await _lazarilloMaps.getPlacesForApiKey('your-api-key');
setState(() {
_places = places.whereType<LzPlace>().toList();
_isLoading = false;
});
} catch (e) {
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error loading places: $e')),
);
}
}
/// Load sub-places for a parent place
Future<List<LzPlace>> _loadSubPlaces(String parentId) async {
final subPlaces = await _lazarilloMaps.getSubPlacesById(parentId);
return subPlaces.whereType<LzPlace>().toList();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Route Creation'),
actions: [
if (_currentRoute != null)
IconButton(
onPressed: _clearRoute,
icon: const Icon(Icons.clear),
tooltip: 'Clear route',
),
],
),
body: Column(
children: [
// Route Configuration Panel
Container(
padding: const EdgeInsets.all(16),
color: Colors.grey.shade100,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Route Configuration',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 16),
// Origin Selection
Row(
children: [
const Icon(Icons.my_location, color: Colors.blue),
const SizedBox(width: 8),
Expanded(
child: DropdownButtonFormField<LzPlace?>(
value: _selectedOrigin,
decoration: const InputDecoration(
labelText: 'Origin (Optional)',
hintText: 'Select origin or use current location',
),
items: [
const DropdownMenuItem(
value: null,
child: Text('Current Location'),
),
..._places.map((place) => DropdownMenuItem(
value: place,
child: Text(place.title),
)),
],
onChanged: (place) {
setState(() {
_selectedOrigin = place;
});
},
),
),
],
),
const SizedBox(height: 16),
// Destination Selection
Row(
children: [
const Icon(Icons.location_on, color: Colors.red),
const SizedBox(width: 8),
Expanded(
child: DropdownButtonFormField<LzPlace?>(
value: _selectedDestination,
decoration: const InputDecoration(
labelText: 'Destination (Required)',
hintText: 'Select destination',
),
items: _places.map((place) => DropdownMenuItem(
value: place,
child: Text(place.title),
)).toList(),
onChanged: (place) {
setState(() {
_selectedDestination = place;
});
},
),
),
],
),
const SizedBox(height: 16),
// Create Route Button
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: _selectedDestination != null ? _createRoute : null,
icon: const Icon(Icons.route),
label: const Text('Create Route'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green,
foregroundColor: Colors.white,
),
),
),
],
),
),
// Current Route Info
if (_currentRoute != null)
Container(
padding: const EdgeInsets.all(16),
color: Colors.green.shade50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(Icons.route, color: Colors.green),
const SizedBox(width: 8),
Text(
'Active Route',
style: Theme.of(context).textTheme.titleMedium,
),
],
),
const SizedBox(height: 8),
Text('Origin: ${_selectedOrigin?.title ?? 'Current Location'}'),
Text('Destination: ${_selectedDestination?.title}'),
// Route distance and duration are on LzRouteLeg, not LzRoute
if (_currentRoute!.legs.isNotEmpty) ...[
Text('Distance: ${_currentRoute!.legs.first.distance}'),
Text('Duration: ${_currentRoute!.legs.first.duration}'),
],
],
),
),
// Map Widget
Expanded(
child: _lazarilloMaps.getLazarilloMapWidget(
MapConfiguration(
latitude: 40.7128,
longitude: -74.0060,
zoom: 15.0,
),
(mapId) => print('Map ready: $mapId'),
),
),
],
),
);
}
Future<void> _createRoute() async {
if (_selectedDestination == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Please select a destination')),
);
return;
}
setState(() {
_isLoading = true;
});
try {
final route = await _lazarilloMaps.addRoute(
RouteConfiguration(
mapId: 'your-map-id',
initialLocation: _selectedOrigin?.position, // Optional origin
finalLocation: _selectedDestination!.position, // Required destination
nextStepsRouteColor: '#FF0000',
prevStepsRouteColor: '#CCCCCC',
polylineWidth: 10.0,
language: 'es',
unitSystem: 'METRIC',
preferAccessibleRoute: true,
),
);
setState(() {
_currentRoute = route;
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
_selectedOrigin != null
? 'Route created from ${_selectedOrigin!.title} to ${_selectedDestination!.title}'
: 'Route created from current location to ${_selectedDestination!.title}'
),
backgroundColor: Colors.green,
),
);
} catch (e) {
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error creating route: $e'),
backgroundColor: Colors.red,
),
);
}
}
Future<void> _clearRoute() async {
try {
await _lazarilloMaps.clearRoute('your-map-id');
setState(() {
_currentRoute = null;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Route cleared')),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error clearing route: $e')),
);
}
}
}Key Features
Origin Fallback Logic
- Flexible Origin: Accepts either a specific place or uses current location
- Automatic Fallback: If no origin is specified, uses current location
- Error Handling: Comprehensive error handling for missing locations
Route Configuration
- Custom Colors: Set colors for next and previous route steps
- Polyline Width: Customize route line thickness
- Language Support: Route instructions in different languages
- Unit System: Metric or imperial units
- Accessibility: Option to prefer accessible routes
Route Information
- Distance: Available on each
LzRouteLegvialeg.distance - Duration: Available on each
LzRouteLegvialeg.duration - Steps: Detailed route instructions per leg
- Visual Display: Route displayed on map with custom styling
Important Notes
- Origin Handling: Always check if origin is available before creating route
- Error Handling: Handle cases where current location is not available
- User Feedback: Provide clear feedback about route creation status
- Route Clearing: Allow users to clear routes when needed
- Places API: Use
getPlacesForApiKey()andgetSubPlacesById()to load places
Advanced Usage
Route with Custom Styling
final route = await lazarilloMaps.addRoute(
RouteConfiguration(
mapId: 'map-id',
finalLocation: destination.position,
nextStepsRouteColor: '#FF0000',
prevStepsRouteColor: '#CCCCCC',
polylineWidth: 15.0,
language: 'en',
unitSystem: 'IMPERIAL',
preferAccessibleRoute: true,
),
);Last updated on