kryonex_address_picker 0.0.6
kryonex_address_picker: ^0.0.6 copied to clipboard
An opinionated, search-first address picker for Flutter with Nominatim geocoding, map confirmation, and structured address output. Built with ForUI and flutter_map.
◆ kryonex_address_picker #
A search-first address picker for Flutter. Geocoding · map confirmation · structured output — in one call.
showAddressPicker(context) → a fully-typed address.
— built by Kryonex Labs —
⟶ Demo #
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 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 |
![]() |
![]() |
|
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, orMapDarkMode.dark - render a custom map pin via
pinBuilder - override the confirm button style with
confirmButtonStyle - control OSM attribution via
AddressPickerAttribution.osmor a customAddressPickerAttribution - position attribution in the map corners with
MapAttributionAlignment.bottomLeftorMapAttributionAlignment.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.
Android — android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
iOS — ios/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>
macOS — DebugProfile.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




