yarrow_map_flutter_sdk 0.0.5 copy "yarrow_map_flutter_sdk: ^0.0.5" to clipboard
yarrow_map_flutter_sdk: ^0.0.5 copied to clipboard

Flutter SDK for Yarrow Maps with API parity to the web SDK.

Yarrow Map Flutter SDK #

Flutter SDK for integrating Yarrow maps in mobile apps, with an API aligned to the Yarrow web SDK.

Table of Contents #


Getting Started #

Installation #

First, add the Yarrow Map Flutter SDK to your project:

flutter pub add yarrow_map_flutter_sdk

Initialization #

To get started, create a YarrowMapController and use YarrowMapView widget to render the map.

Important - Coordinate Format: This SDK uses (lng: number, lat: number) named tuples for map configuration, matching the MapLibre convention.

import 'package:flutter/material.dart';
import 'package:yarrow_map_flutter_sdk/yarrow_map_flutter_sdk.dart';

class MapScreen extends StatefulWidget {
  const MapScreen({super.key});

  @override
  State<MapScreen> createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  final controller = YarrowMapController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: YarrowMapView(
        config: const YarrowMapConfig(
          center: (lng: 69.2401, lat: 41.2995),
          apiKey: 'YOUR_API_KEY',
          zoom: 12,
        ),
        controller: controller,
        onReady: (map) async {
          await map.zoomTo(41.2995, 69.2401, 14);
        },
      ),
    );
  }
}

Configuration Options #

The YarrowMapConfig class accepts the following configuration options:

const mapConfig = YarrowMapConfig(
  center: (lng: 69.2401, lat: 41.2995),    // Required: center coordinates
  apiKey: 'YOUR_API_KEY',                    // Required: your Yarrow API key
  zoom: 12,                                  // Initial zoom level (default: 10)
  minZoom: 5,                                // Minimum zoom level (default: 0)
  maxZoom: 18,                                // Maximum zoom level (default: 19)
  theme: YarrowMapTheme.dark,                // 'light' or 'dark' (default: 'light')
  brandBadgePosition: BrandBadgePosition.topRight,  // Badge position
  controls: YarrowControlsConfig(
    enabled: true,                            // Controls are OFF by default
    position: YarrowControlsPosition.rightBottom, // Optional placement
    showZoom: true,                           // Show zoom buttons
    showCompass: true,                        // Show compass
  ),
);

Example with all options:

import 'package:flutter/material.dart';
import 'package:yarrow_map_flutter_sdk/yarrow_map_flutter_sdk.dart';

class FullConfigMapScreen extends StatelessWidget {
  const FullConfigMapScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: YarrowMapView(
        config: const YarrowMapConfig(
          center: (lng: 69.2401, lat: 41.2995),
          apiKey: 'YOUR_API_KEY',
          zoom: 12,
          minZoom: 5,
          maxZoom: 18,
          theme: YarrowMapTheme.dark,
          brandBadgePosition: BrandBadgePosition.topRight,
          controls: YarrowControlsConfig(
            enabled: true,
            position: YarrowControlsPosition.rightBottom,
            showZoom: true,
            showCompass: true,
          ),
        ),
        controller: YarrowMapController(),
        onReady: (map) {
          print('Map ready!');
        },
      ),
    );
  }
}

When controls and the brand badge are placed in the same corner (for example rightBottom with brandBadgePosition.bottomRight), the SDK automatically adds spacing so they do not overlap.

Basic Map Manipulation #

Changing the Map Style #

You can change the map's visual style. The available styles are satellite, hybrid, and the default map style.

// Switch to satellite view
await map.changeStyles(styleType: YarrowMapStyleType.satellite);

// Switch to hybrid view (satellite with labels)
await map.changeStyles(styleType: YarrowMapStyleType.hybrid);

// Switch back to the default map style
await map.changeStyles();

Changing the Map Theme #

You can set the initial theme in the configuration or switch between light and dark themes dynamically after initialization.

Setting initial theme:

const mapConfig = YarrowMapConfig(
  center: (lng: 69.2401, lat: 41.2995),
  apiKey: 'YOUR_API_KEY',
  zoom: 12,
  theme: YarrowMapTheme.dark, // Set initial theme to dark
);

Switching theme dynamically:

// Switch to dark mode
await map.changeTheme(YarrowMapTheme.dark);

// Switch to light mode (default)
await map.changeTheme(YarrowMapTheme.light);

Changing Brand Badge Position #

You can set the initial badge position in config or change it dynamically after map initialization.

// Move badge to the top-right corner
map.changeBrandBadgePosition(BrandBadgePosition.topRight);

// Other values: BrandBadgePosition.topLeft, .bottomLeft, .bottomRight

Moving the Map View #

You can programmatically move the map to a new location or fit it to a specific geographic area.

Zooming to a specific point:

// Fly to a new location with a specific zoom level
map.zoomTo(41.3111, 69.2797, 15); // Latitude, Longitude, Zoom Level

Fitting the map to a set of features:

This is useful when you want to display a set of points, lines, or polygons and ensure they are all visible.

final geojsonData = {
  'type': 'FeatureCollection',
  'features': [
    // Your GeoJSON features here
  ],
};

map.fitBounds(geojsonData);

Handling Events #

You can listen for various user interactions with the map.

Listen for Map Movement #

Execute a callback function whenever the map finishes moving.

map.onMoveEnd((lat, lng, zoom) {
  print('Map moved to: $lat, $lng with zoom: $zoom');
});

Listen for Map Clicks #

Execute a callback when the user clicks on the map.

map.onMapClick((lat, lng) {
  print('Map clicked at: $lat, $lng');
});

Listen for Clicks on POIs or Buildings #

You can add click listeners to specific groups of features on the map, like points of interest (POIs) or buildings.

// Listen for clicks on POIs
map.onIconClick(YarrowLayerGroup.pois, (lat, lng, properties) {
  print('POI clicked: $properties');
});

// Listen for clicks on buildings
map.onIconClick(YarrowLayerGroup.buildings, (lat, lng, properties) {
  print('Building clicked: $properties');
});

Working with Layers and Data #

Adding a GeoJSON Layer #

You can add custom data to the map in the form of a GeoJSON layer. This is useful for displaying points, lines, or polygons.

final myData = {
  'type': 'FeatureCollection',
  'features': [
    {
      'type': 'Feature',
      'geometry': {
        'type': 'Point',
        'coordinates': [69.2797, 41.3111],
      },
      'properties': {
        'name': 'My Point',
      },
    },
  ],
};

map.addLayer(
  'my-custom-layer', // A unique name for the layer
  'circle', // The type of layer (e.g., 'circle', 'line', 'fill', 'symbol')
  myData,
  paint: {
    'circle-radius': 10,
    'circle-color': '#ff0000',
  },
);

Advanced Layer Configuration #

The addLayer method supports advanced configuration options for different layer types:

map.addLayer(
  'layerName',        // String - Unique identifier for the layer
  'symbol',           // Layer type: 'symbol', 'fill', 'line', 'background', 'raster', 'circle', 'heatmap', 'fill-extrusion', 'hillshade'
  featureCollection,  // GeoJSON FeatureCollection
  paint: {            // Paint properties map
    'text-halo-color': '#ffffff',
    'text-halo-width': 2,
  },
  layout: {           // Layout properties map
    'icon-image': 'custom-icon',
    'icon-size': 0.8,
    'text-field': ['get', 'name'],
  },
  options: YarrowAddLayerOptions(
    sourceId: 'my-source',
    filter: ['==', ['get', 'status'], 'active'],
  ),
);

Managing Sources Explicitly #

map.addSource('vehicles-source', vehicleFeatureCollection);
map.updateSourceData('vehicles-source', nextVehicleFeatureCollection);

map.addLayer(
  'active-vehicles',
  'circle',
  nextVehicleFeatureCollection,
  paint: {
    'circle-radius': {'type': 'interpolate', 'input': {'type': 'zoom'}, 'stops': [[10, 4], [16, 10]]},
    'circle-color': {'type': 'case', 'condition': ['==', ['get', 'status'], 'active'], 'true': '#16a34a', 'false': '#9ca3af']},
  },
  options: YarrowAddLayerOptions(
    sourceId: 'vehicles-source',
    filter: ['==', ['get', 'status'], 'active'],
  ),
);

Feature State and Rendered Queries:

map.setFeatureState(
  source: 'vehicles-source',
  id: 101,
  state: {'selected': true},
);

final features = map.queryRenderedFeatures(
  options: YarrowQueryRenderedFeaturesOptions(layers: ['active-vehicles']),
);

Adding and Removing Markers #

You can add markers to the map to indicate specific locations.

// Add a simple marker
final marker = map.addMarker(41.3111, 69.2797); // latitude, longitude

// Add a marker with options
final customMarker = map.addMarker(
  41.2995,
  69.2401,
  color: '#0000ff',          // Marker color (default: '#FF0000')
  draggable: true,            // Allow dragging (default: false)
  anchor: YarrowMarkerAnchor.bottom,  // Anchor position
  onClick: () {               // Click event handler
    print('Marker clicked!');
  },
);

// Remove a marker
map.removeMarker(marker);

Removing a Layer #

You can remove a layer that you've previously added.

map.removeLayer('my-custom-layer');

Routing #

The SDK provides powerful routing capabilities.

Building and Displaying a Simple Route #

Calculate and display a route between a start and end point.

final start = (lat: 41.2995, lng: 69.2401);
final end = (lat: 41.3111, lng: 69.2797);
const profile = 'car'; // 'car', 'bicycle', or 'pedestrian'

final result = await map.buildRouteWithLabels(start, end, profile);
print('Route built: ${result.features}');
print('Directions: ${result.directions}');

Building and Displaying a Multi-Stop Route #

You can also create a route that passes through multiple waypoints.

final coordinates = [
  (lat: 41.2995, lng: 69.2401), // Start
  (lat: 41.3111, lng: 69.2797), // Waypoint 1
  (lat: 41.325, lng: 69.285),   // End
];
const profile = 'car';
const language = 'en'; // Optional: 'en', 'ru', etc. (default: 'ru')

final result = await map.buildMultiSegmentRouteWithLabels(coordinates, profile, language);
print('Multi-segment route built: ${result.features}');
print('Directions: ${result.directions}');

Clearing Routes #

To remove all route-related layers from the map:

map.clearAllRoutes();

Highlighting Search Results #

You can perform a search and display the results on the map. The search is performed around the current map center.

const query = 'Tashkent';

final clearHighlights = map.highlightSearchResults(
  query,
  zoomToResults: true, // Automatically zoom to fit the results
  onResultsUpdate: (results) {
    print('Search results: $results');
  },
  onLoadingStateChange: (state) {
    // state can be 'firstRender', 'rerender', or null
    print('Loading state: $state');
  },
);

// To remove the search results from the map later
clearHighlights();

Public Transport #

Displaying Real-Time Bus Locations #

You can display the real-time locations of buses on the map.

Show buses for a specific route:

const routeId = 'some-route-id';
final clearBusRoute = await map.showBusRoute(routeId);

// To stop showing the bus route later
// clearBusRoute();

Show all buses in the current map view:

If you don't provide a routeId, the map will show all buses within the visible area.

final clearBusRoutes = await map.showBusRoute();

// To stop showing all bus routes
// clearBusRoutes();

Clearing Bus Routes #

The showBusRoute method returns a cleanup function that you can call to stop displaying bus locations and remove all related data:

// Store the cleanup function
final clearBuses = await map.showBusRoute('route-123');

// Later, clear the bus route display
clearBuses();

Utility Methods #

Calculating Bounding Box #

The SDK provides a utility method to calculate the bounding box of GeoJSON data:

final geojsonData = {
  'type': 'FeatureCollection',
  'features': [
    {
      'type': 'Feature',
      'geometry': {
        'type': 'Point',
        'coordinates': [69.2797, 41.3111],
      },
    },
    {
      'type': 'Feature',
      'geometry': {
        'type': 'LineString',
        'coordinates': [
          [69.240, 41.299],
          [69.280, 41.311],
        ],
      },
    },
  ],
};

final boundingBox = map.getBoundingBox(geojsonData);
print(boundingBox);
// Output: { xMin: 69.240, xMax: 69.280, yMin: 41.299, yMax: 41.3111 }

Supported Geometry Types:

  • Point
  • LineString
  • Polygon

The bounding box contains:

  • xMin: Minimum longitude
  • xMax: Maximum longitude
  • yMin: Minimum latitude
  • yMax: Maximum latitude

API Reference #

YarrowMapConfig #

class YarrowMapConfig {
  final ({double lng, double lat}) center;  // Required
  final String apiKey;                        // Required: Yarrow API key
  final double zoom;                          // default: 10
  final double minZoom;                       // default: 0
  final double maxZoom;                       // default: 19
  final YarrowMapTheme theme;                 // default: light
  final BrandBadgePosition? brandBadgePosition;
  final YarrowControlsConfig? controls;
}

YarrowControlsConfig #

class YarrowControlsConfig {
  final bool enabled;                            // default: false
  final YarrowControlsPosition position;         // default: right
  final bool showZoom;                          // default: true
  final bool showCompass;                       // default: true
}

YarrowMapController #

Method Parameters Return Type Description
zoomTo lat: double, lng: double, zoom: double void Fly to specific coordinates
fitBounds data: Map<String, dynamic> void Fit map to show all features
getBoundingBox data: Map<String, dynamic> YarrowBoundingBox Calculate bounding box of features
changeStyles styleType?: YarrowMapStyleType Future<void> Change map style
changeTheme theme: YarrowMapTheme Future<void> Switch between light and dark themes
changeBrandBadgePosition position: BrandBadgePosition void Change brand badge position at runtime
onMoveEnd callback: Function void Listen for map movement end
onMapClick callback: Function void Listen for map clicks
onIconClick layerGroup: YarrowLayerGroup, callback: Function void Listen for icon clicks
addSource sourceId: String, data: Map<String, dynamic> void Add/replace a GeoJSON source
updateSourceData sourceId: String, data: Map<String, dynamic> void Update data for an existing GeoJSON source
addLayer name: String, type: String, data: Map<String, dynamic>, ... void Add a layer to the map
setFeatureState {source: String, id: dynamic}, state: Map<String, dynamic> void Set state for a specific feature
queryRenderedFeatures options: YarrowQueryRenderedFeaturesOptions List<Map<String, dynamic>> Query currently rendered features
removeLayer layerName: String void Remove a layer from the map
addMarker lat: double, lng: double, options?: YarrowMarkerOptions YarrowMarker? Add a marker to the map
removeMarker marker: YarrowMarker void Remove a marker from the map
buildRouteWithLabels start: (lat: double, lng: double), end: (lat: double, lng: double), profile: String Future<YarrowRouteResult> Build and display a route
buildMultiSegmentRouteWithLabels coordinates: List<(lat: double, lng: double)>, profile: String, language?: String Future<YarrowRouteResult> Build multi-segment route
clearAllRoutes None void Clear all route layers and popups
highlightSearchResults query: String, options?: YarrowSearchOptions void Function() Highlight search results with cleanup function
showBusRoute routeId?: String Future<void Function()> Show bus locations with cleanup function

Type Definitions #

// Bounding Box
class YarrowBoundingBox {
  final double xMin;
  final double xMax;
  final double yMin;
  final double yMax;
}

// Route Result
class YarrowRouteResult {
  final List<dynamic> features;
  final List<dynamic> directions;
}

// Marker Options
class YarrowMarkerOptions {
  final String? color;
  final bool draggable;
  final YarrowMarkerAnchor anchor;
  final void Function()? onClick;
}

// Search Options
class YarrowSearchOptions {
  final String? layerName;
  final String? iconImage;
  final String? highlightColor;
  final bool pulseAnimation;
  final bool zoomToResults;
  final void Function(double lat, double lng, Map<String, dynamic> properties)? onIconClick;
  final void Function(List<dynamic> results)? onResultsUpdate;
  final void Function(String? state)? onLoadingStateChange;
}

// Layer Options
class YarrowAddLayerOptions {
  final String? sourceId;
  final List<dynamic>? filter;
}

// Query Options
class YarrowQueryRenderedFeaturesOptions {
  final List<String>? layers;
  final List<String>? sourceLayers;
}

Version Information #

  • Current Version: 0.0.5
  • Dependencies: maplibre_gl ^0.25.0, dio ^5.9.0, flutter_cache_manager ^3.4.1, flutter_svg ^2.2.2
  • Changelog: CHANGELOG.md

Notes #

  • This package uses maplibre_gl under the hood.
  • Ensure platform setup for Flutter + MapLibre is completed in your app.

Support #

For issues, questions, or contributions, contact the Yarrow development team.

1
likes
110
points
214
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flutter SDK for Yarrow Maps with API parity to the web SDK.

Homepage

License

unknown (license)

Dependencies

dio, flutter, flutter_cache_manager, flutter_svg, maplibre_gl

More

Packages that depend on yarrow_map_flutter_sdk