native_address_autocomplete
A customizable Flutter address autocomplete TextField powered by native platform APIs.
Features
- No Google API key required.
- iOS uses Apple MapKit
MKLocalSearchCompleter. - Android uses the platform
Geocoder. - Includes a TextField-style widget with a dropdown.
- Customize debounce, minimum characters, result limit, countries, dropdown height, item UI, and the full suggestions list.
- Shows a trailing loading indicator while searching.
- Optional clear button, error UI, keyboard navigation, and matched-text highlight.
- Resolve a selected suggestion into coordinates and address components.
- Optional
FormFieldand external state controller. - Use the system language by default, or pass a custom locale where supported.
Android Geocoder is best-effort and depends on the device's available geocoding
service. It is useful for lightweight address suggestions, but it is not a full
replacement for Google Places Autocomplete in delivery-critical flows.
Usage
NativeAddressAutocompleteTextField(
addressController: AddressAutocompleteController(),
countries: const ['US', 'CA'],
limit: 5,
dropdownMaxHeight: 280,
showLoadingIndicator: true,
showClearButton: true,
resolveOnSelected: true,
useSystemLocale: true,
// Android applies this locale to Geocoder. iOS MapKit follows system/app
// language and ignores per-request locale overrides.
locale: const Locale('fr', 'CA'),
resultTypes: const {
AddressResultType.address,
AddressResultType.pointOfInterest,
},
decoration: const InputDecoration(
labelText: 'Address',
border: OutlineInputBorder(),
),
itemBuilder: (context, suggestion, index) {
return ListTile(
title: Text(suggestion.primaryText),
subtitle: suggestion.secondaryText == null
? null
: Text(suggestion.secondaryText!),
);
},
onSelected: (suggestion) {
debugPrint(suggestion.fullText);
},
onResolved: (address) {
debugPrint(address.city);
debugPrint('${address.latitude}, ${address.longitude}');
},
errorBuilder: (context, error) {
return const Padding(
padding: EdgeInsets.all(16),
child: Text('Could not load suggestions.'),
);
},
)
Use it inside a Form:
final formKey = GlobalKey<FormState>();
Form(
key: formKey,
child: NativeAddressAutocompleteFormField(
showClearButton: true,
validator: (address) {
return address == null ? 'Address required' : null;
},
onSaved: (address) {
debugPrint(address?.fullText);
},
),
)
Customize the trailing loading indicator:
NativeAddressAutocompleteTextField(
loadingIndicatorBuilder: (context) {
return const Padding(
padding: EdgeInsets.all(12),
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
);
},
)
You can also use the client directly:
const autocomplete = NativeAddressAutocomplete();
final available = await autocomplete.isAvailable();
final suggestions = await autocomplete.suggest(
'1600 Amph',
countries: const ['US'],
limit: 5,
resultTypes: const {AddressResultType.address},
localeTag: 'zh-Hant-TW',
);
final address = await autocomplete.resolve(suggestions.first);
debugPrint(address?.street);
debugPrint(address?.postalCode);
The dropdown opens below the text field. If there is not enough room, it uses the available height and scrolls its contents.
Platform notes
- iOS suggestions use
MKLocalSearchCompleter; selected suggestions are resolved withMKLocalSearch. - Android suggestions and resolution use
Geocoder. Availability and quality depend on the device geocoding service. locale/localeTagis applied on Android. iOS MapKit uses the system/app language for local search results.