◆ kryonex_address_picker

A search-first address picker for Flutter. Geocoding · map confirmation · structured output — in one call.

showAddressPicker(context) → a fully-typed address.

Pub Version Pub Likes Pub Points Pub Popularity

GitHub Stars GitHub Forks GitHub Issues Last Commit

License Platform Dart Flutter

Style PRs Welcome Kryonex Labs

— built by Kryonex Labs


⟶ Demo

example

Search · confirm on map · capture details — all in one flow.

Screenshots

Part 1 — Finding a location

1. Entry point 2. Search 3. Map confirm
Host app entry point Search screen Map confirm screen
Host app launches the picker by calling showAddressPicker(context).
See example/lib/main.dart · HomePage
Debounced Photon autocomplete, Use current location (opens map confirm at the resolved location), and Pick on Map entry points. Recent picks appear here too.
See lib/src/screens/search_screen.dart
Tap-to-drop pin on an OSM map with reverse geocoding, a "Locate Me" FAB, and the live address card.
See lib/src/screens/map_confirm_screen.dart

Part 2 — Capturing details & result

4. Detail sheet 5. Result
Detail bottom sheet Selected address result
Frosted-glass bottom sheet collecting custom fields — Apt, Floor, a custom Gate code with quick-fill chips, Postal Code, and Delivery Notes.
Configured via AddressFieldSpec — see the Configurable detail fields section
The returned SelectedAddress rendered back in the host app — structured address fields plus the captured detail values.
See example/lib/main.dart · result rendering

⟶ Why

Address entry is usually a mess of free-text fields and bad data. This is the opposite: type, confirm on a map, done. You get back clean, structured, geocoded results.

Powered by Komoot Photon (OpenStreetMap data, no API key), flutter_map, and ForUI components.

⟶ Features

◆ Search-first           debounced Photon autocomplete
◆ Map confirmation       tap-to-drop pin on an interactive OSM map
◆ Structured output      street · city · state · postal · country · latLng
◆ Address details        apt · floor · delivery notes
◆ Recent addresses       locally persisted picks
◆ Current location        opens map confirm after resolving coordinates
◆ Map styling            light / dark / auto tile mode
◆ Custom pin marker      `pinBuilder` support for any marker widget
◆ Confirm button styling override via `confirmButtonStyle`
◆ Attribution control    declarative OSM attribution and alignment
◆ ForUI native           polished, accessible UI out of the box
◆ Zero-config theming    auto-bridges to your Material theme

⟶ Install

dependencies:
  kryonex_address_picker: ^0.1.0

⟶ Quick Start

import 'package:kryonex_address_picker/kryonex_address_picker.dart';

final result = await showAddressPicker(context);
if (result != null) {
  result.address.displayName;   // "123 Main St, Springfield, IL 62701, USA"
  result.address.street;        // "Main Street"
  result.address.city;          // "Springfield"
  result.address.latLng;        // LatLng(39.7817, -89.6501)
  result.details?.apt;          // "Apt 4B"
  result.details?.deliveryNotes; // "Leave at the door"
}

With configuration:

final result = await showAddressPicker(
  context,
  config: AddressPickerConfig(
    countryCodes: ['us', 'ca'],
    maxRecentAddresses: 10,
    searchHint: 'Where to?',
    showDetailScreen: true,
    detailFields: [
      AddressFieldSpec.apt,
      AddressFieldSpec.deliveryNotes,
    ],
  ),
);

Configurable detail fields

The detail step is a frosted-glass bottom sheet presented over the confirmed map. Its fields are fully composable via AddressFieldSpec: mix the built-in presets with your own custom fields, with per-field icons, validation, keyboard types, and quick-fill chips.

Built-in presets: AddressFieldSpec.apt, .floor, and .deliveryNotes (the default set), plus .postalCode (opt-in — handy for international addresses).

config: AddressPickerConfig(
  detailFields: [
    AddressFieldSpec.apt,          // built-in preset
    AddressFieldSpec.floor,        // built-in preset
    AddressFieldSpec(              // custom field
      key: 'gate',
      label: 'Gate code',
      icon: Icons.pin_outlined,
      keyboardType: TextInputType.number,
      required: true,
      quickFills: ['1234', '0000'],
    ),
    AddressFieldSpec.deliveryNotes,
  ],
),

// Read values back by key:
result.details?['gate'];      // "1234"
result.details?.apt;          // built-in convenience getter, still works

Pre-filling fields from the confirmed address

Use prefillFrom to seed a field with an attribute captured during map confirmation. The user can still edit the value before saving.

AddressFieldSpec(
  key: 'city',
  label: 'City',
  icon: Icons.location_city_outlined,
  prefillFrom: AddressAttribute.city,   // seeds the field on sheet open
),

// The built-in postalCode preset pre-fills automatically:
AddressFieldSpec.postalCode,

AddressAttribute covers every field on StructuredAddress: displayName, street, houseNumber, city, state, postalCode, country, countryCode, latitude, longitude, primaryLine, secondaryLine.

You can also use AddressAttributeReader.readAttribute(attribute) to extract any attribute value as a string.

The sheet's appearance is configurable too — see detailSheetTitle, detailSheetSubtitle, saveButtonLabel, sheetBlurSigma, sheetCornerRadius, sheetAccentColor, showDragHandle, sheetDismissible, and sheetEnableDrag in the table below.

Map customization

The picker also supports map-specific customization via AddressPickerConfig. Use the configuration fields below to:

  • toggle tile dark mode with MapDarkMode.auto, MapDarkMode.light, or MapDarkMode.dark
  • render a custom map pin via pinBuilder
  • override the confirm button style with confirmButtonStyle
  • control OSM attribution via AddressPickerAttribution.osm or a custom AddressPickerAttribution
  • position attribution in the map corners with MapAttributionAlignment.bottomLeft or MapAttributionAlignment.bottomRight

⟶ Configuration

Parameter Type Default Description
theme FThemeData? null Explicit ForUI theme (highest priority)
materialTheme ThemeData? null Material theme to auto-bridge
initialLocation LatLng? null Initial map center
countryCodes List<String>? null ISO country-code filter for search (takes priority over localeAwareSearch)
localeAwareSearch bool true Auto-restrict results to the device locale's country (ignored when countryCodes is set)
maxRecentAddresses int 5 Max recent addresses to store
showDetailScreen bool true Show the detail sheet after map confirm
detailFields List<AddressFieldSpec>? apt, floor, notes Which detail fields to display, and in what order
searchHint String? null Search bar placeholder (falls back to "Search for an address...")
mapZoom double 16.0 Default map zoom level
mapDarkMode MapDarkMode auto Controls tile dark-mode emulation: auto, light, or dark
pinBuilder WidgetBuilder? null Custom map pin widget builder; renders instead of the default MapPin
confirmButtonStyle ButtonStyle? null Override the style of the Confirm Address button
attributionStyle AddressPickerAttribution? AddressPickerAttribution.osm Configures OSM attribution text, URI, background, and alignment; set to null to hide it
detailSheetTitle String "Add details" Title at the top of the detail sheet
detailSheetSubtitle String? null Optional subtitle under the title
saveButtonLabel String "Save address" Label for the sheet's save button
sheetBlurSigma double 18.0 Backdrop blur strength behind the sheet
sheetCornerRadius double 28.0 Sheet top corner radius
sheetAccentColor Color? theme primary Glow colour of the save button
showDragHandle bool true Show the drag handle
sheetDismissible bool true Tap-scrim to dismiss
sheetEnableDrag bool true Drag-down to dismiss

⟶ Output Model

class SelectedAddress {
  final StructuredAddress address;
  final AddressDetails? details;
}

class StructuredAddress {
  final String displayName;     // Full address string
  final LatLng latLng;          // Geographic coordinates
  final String? street;         // "Main Street"
  final String? houseNumber;    // "123"
  final String? city;           // "Springfield"
  final String? state;          // "Illinois"
  final String? postalCode;     // "62701"
  final String? country;        // "United States"
  final String? countryCode;    // "us"
}

class AddressDetails {
  final Map<String, String?> values; // keyed by AddressFieldSpec.key

  String? operator [](String key);   // values['gate']
  String? get apt;                   // convenience: values['apt']
  String? get floor;                 // convenience: values['floor']
  String? get deliveryNotes;         // convenience: values['deliveryNotes']

  bool get isEmpty;                  // true when no field has a value
  bool get isNotEmpty;
}

⟶ Theming

The picker adapts to your app automatically, in priority order:

// 1 — Explicit ForUI theme (highest priority)
showAddressPicker(context, config: AddressPickerConfig(
  theme: FThemes.zinc.dark,
));

// 2 — Material theme bridge
showAddressPicker(context, config: AddressPickerConfig(
  materialTheme: ThemeData(colorSchemeSeed: Colors.blue),
));

// 3 — Auto-detect (zero config)
showAddressPicker(context);

⟶ Platform Setup

Location permissions (geolocator)

The "Use current location" feature needs platform-specific permissions.

Androidandroid/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

iOSios/Runner/Info.plist:

<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to find nearby addresses.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>We need your location to find nearby addresses.</string>

macOSDebugProfile.entitlements and Release.entitlements:

<key>com.apple.security.personal-information.location</key>
<true/>

Web — no setup needed; uses the browser Geolocation API.

Internet permission (Android)

Required for Photon API calls and map tiles — AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Kryonex Labs · MIT License

Geocoding by Komoot Photon · OpenStreetMap data

Libraries

kryonex_address_picker
An opinionated, search-first address picker for Flutter.