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
100
points
7
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