Location Picker Plus
Advanced Flutter location picker with Google Places API integration, GPS detection, manual entry, and comprehensive theming. The ultimate solution for location selection with fallback options.
π v3.0.0 - Major Release with Google Places Integration
π Three Powerful Widgets for Every Use Case
π LocationPickerWidget
Traditional dropdown selection from predefined country/state/city data with beautiful customization.
π LocationDetectorWidget
Live GPS location detection and address geocoding with real-time coordinate conversion.
π₯ LocationPickerPlusUnifiedWidget (NEW v3.0.0)
All-in-one widget combining Google Places Autocomplete, GPS detection, and manual entry with intelligent tab-based interface.
Features
Traditional Location Picker
- β Two Input Modes - Dropdown with search OR Real-time autocomplete
- β Instant Suggestions - See suggestions as you type (no Enter key needed)
- β Debounced Performance - Optimized for smooth typing experience
- β Customizable Themes - Multiple pre-built themes and full customization support
- β Smart Search - Built-in search with relevance sorting
- β Flag Emojis & Phone Codes - Display country flags and phone codes
- β Flexible Layouts - Horizontal/vertical layouts with responsive design
- β Asset-based Data - Load location data from JSON assets
- β Enhanced Models - Rich data models with additional properties
- β Animation Support - Smooth transitions and animations
- β Accessibility - Screen reader support and keyboard navigation
π Live Location Detection
- π GPS Location Detection - Get current location with one tap
- π Address Geocoding - Search any address and get coordinates
- π Reverse Geocoding - Convert coordinates to readable addresses
- π Forward Geocoding - Convert addresses to coordinates
- π Auto Permission Handling - Handles all location permissions automatically
- β‘ High Accuracy GPS - Configurable accuracy levels
- π Multi-locale Support - Address detection in multiple languages
- π± Cross-platform - Full Android and iOS support
- ποΈ Flexible Modes - GPS only, search only, or both
- π¨ Full UI Customization - Match your app's design
π NEW v3.0.0 - Google Places Integration
- π Google Places Autocomplete - Real-time address search with global coverage
- π’ Business & POI Support - Find restaurants, hotels, landmarks, and more
- π Tabbed Interface - Clean navigation between Google Places, GPS, and manual entry
- π Smart Field Locking - Auto-lock fields when address selected from Google Places
- π Country Restrictions - Limit search results to specific countries
- π Address Source Tracking - Know if address came from Google Places, GPS, or manual entry
- π¨ Enhanced Theming - Comprehensive theming system with Material and Cupertino themes
- π± Mobile Optimized - Touch-friendly interface with responsive design
Installation
Add this to your package's pubspec.yaml
file:
dependencies:
location_picker_plus: ^3.0.0
ποΈ Google Places API Setup (NEW v3.0.0)
- Get API Key: Visit Google Cloud Console
- Enable APIs: Enable "Places API" in your project
- Configure Billing: Ensure billing is enabled for your project
- Restrict Key (recommended): Restrict your API key to specific platforms
LocationPickerPlusUnifiedWidget(
googlePlacesApiKey: 'YOUR_API_KEY_HERE',
// ... other parameters
)
π± Platform Setup (for GPS Location Features)
Android
Add to android/app/src/main/AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
iOS
Add to ios/Runner/Info.plist
:
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to detect your current location.</string>
Usage
π Live Location Detection
Quick Start
import 'package:location_picker_plus/location_picker_plus.dart';
LocationDetectorWidget(
mode: LocationDetectorMode.both, // GPS + Address search
showCoordinates: true,
onLocationChanged: (location) {
print('Lat: ${location?.latitude}, Lng: ${location?.longitude}');
print('Address: ${location?.fullAddress}');
print('City: ${location?.locality}');
print('State: ${location?.administrativeArea}');
print('Country: ${location?.country}');
},
)
GPS Detection Only
LocationDetectorWidget(
mode: LocationDetectorMode.currentLocation,
onCoordinatesChanged: (lat, lng) {
print('Coordinates: $lat, $lng');
},
)
Address Search Only
LocationDetectorWidget(
mode: LocationDetectorMode.addressSearch,
addressSearchHint: 'Enter address, city, or landmark...',
onLocationChanged: (location) {
// Use detected location data
},
)
Advanced Usage with Service
// Direct service usage for custom UI
LocationDetectorService service = LocationDetectorService.instance;
// Get current location
LocationModel? location = await service.getCurrentLocationWithAddress();
print('Current city: ${location?.locality}');
// Search address
LocationModel? searched = await service.getCoordinatesFromAddress('New York');
print('NYC coordinates: ${searched?.latitude}, ${searched?.longitude}');
π₯ Unified Location Picker with Google Places Integration (NEW v3.0.0)
The ultimate all-in-one widget combining Google Places Autocomplete, GPS detection, and manual entry with intelligent tab-based interface and smart field management.
π― Smart Field Behavior
- Google Places Selection β Fields automatically lock for accuracy
- Manual Entry β All fields remain fully editable
- GPS Location β All fields remain editable
- Country Restrictions β Limit countries in dropdown
Quick Start - All Modes
LocationPickerPlusUnifiedWidget(
mode: LocationPickerMode.all, // Show all 3 tabs
googlePlacesApiKey: 'your-api-key',
allowedCountries: ['India', 'United States'], // Optional restriction
lockFieldsForGooglePlaces: true, // Default: true
onLocationSelected: (location) {
print('Selected: ${location?.address}');
print('Source: ${location?.addressSource}'); // googlePlaces, manualEntry, or gpsLocation
if (location?.addressSource == AddressSource.googlePlaces) {
print('Address from Google Places - fields are locked');
} else {
print('Manual/GPS address - fields are editable');
}
},
)
Google Places Only Mode
LocationPickerPlusUnifiedWidget(
mode: LocationPickerMode.googlePlaces,
googlePlacesApiKey: 'your-api-key',
country: 'US', // Restrict to US addresses
placesTypes: ['establishment', 'geocode'],
onLocationSelected: (location) {
// Google Places result with locked fields in manual entry
},
)
Manual Entry with Country Restrictions
LocationPickerPlusUnifiedWidget(
mode: LocationPickerMode.manualEntry,
allowedCountries: ['IN', 'US', 'CA'], // ISO codes or full names
lockFieldsForGooglePlaces: false, // Allow editing Google Places results
onLocationSelected: (location) {
// Manual entry result - always editable
},
)
GPS + Manual Entry (No Google Places)
LocationPickerPlusUnifiedWidget(
mode: LocationPickerMode.all,
googlePlacesApiKey: null, // Disable Google Places tab
autoDetectOnInit: true, // Auto-detect GPS on load
allowedCountries: ['India', 'United States'],
onLocationSelected: (location) {
// GPS or manual entry result
},
)
Address Source Tracking
onLocationSelected: (LocationResult? location) {
switch (location?.addressSource) {
case AddressSource.googlePlaces:
print('π From Google Places - High accuracy, fields locked');
break;
case AddressSource.manualEntry:
print('βοΈ Manual entry - User can edit all fields');
break;
case AddressSource.gpsLocation:
print('π From GPS - Detected location, fields editable');
break;
}
}
π Traditional Location Picker
Basic Usage
LocationPickerWidget(
onCountryChanged: (country) {
print('Selected country: ${country?.name}');
},
onStateChanged: (state) {
print('Selected state: ${state?.name}');
},
onCityChanged: (city) {
print('Selected city: ${city?.name}');
// Access latitude/longitude from city data
if (city?.latitude != null) {
print('City coordinates: ${city?.latitude}, ${city?.longitude}');
}
},
)
Autocomplete Mode (Real-time suggestions as you type)
LocationPickerWidget(
useAutocomplete: true, // Enable autocomplete mode
countryHint: 'Type country name...',
stateHint: 'Type state name...',
cityHint: 'Type city name...',
onCountryChanged: (country) {
// Handle country selection
},
)
Dropdown Mode (Traditional dropdown with search)
LocationPickerWidget(
useAutocomplete: false, // Traditional dropdown mode
theme: LocationPickerTheme.materialTheme().copyWith(
showFlags: true,
showPhoneCodes: true,
borderRadius: BorderRadius.circular(12),
),
countryLabel: 'Country',
stateLabel: 'State/Province',
cityLabel: 'City',
onCountryChanged: (country) {
// Handle country selection
},
)
Country Only Picker
LocationPickerWidget(
useAutocomplete: true, // Or false for dropdown
showState: false,
showCity: false,
countryHint: 'Type country name...',
onCountryChanged: (country) {
// Handle country selection
},
)
Horizontal Layout
Row(
children: [
Expanded(
child: LocationPickerWidget(
showState: false,
showCity: false,
countryLabel: 'Country',
),
),
SizedBox(width: 16),
Expanded(
child: LocationPickerWidget(
showCountry: false,
showCity: false,
stateLabel: 'State',
),
),
],
)
π Combining Both Widgets
You can use both widgets together for maximum flexibility:
Column(
children: [
// Live location detection
LocationDetectorWidget(
mode: LocationDetectorMode.currentLocation,
onLocationChanged: (location) {
// Auto-fill traditional picker based on detected location
},
),
SizedBox(height: 20),
// Traditional picker for manual selection
LocationPickerWidget(
useAutocomplete: true,
onCountryChanged: (country) {
// Handle manual selection
},
),
],
)
Customization
Available Themes
// Default theme
LocationPickerTheme.defaultTheme()
// Material Design theme
LocationPickerTheme.materialTheme()
// Cupertino theme
LocationPickerTheme.cupertinoTheme()
// Custom theme
LocationPickerTheme(
inputDecoration: InputDecoration(
border: OutlineInputBorder(),
contentPadding: EdgeInsets.all(16),
),
dropdownBackgroundColor: Colors.white,
itemHighlightColor: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
elevation: 4,
showFlags: true,
showPhoneCodes: false,
maxHeight: 250,
animationDuration: Duration(milliseconds: 200),
)
Input Modes
Autocomplete Mode (useAutocomplete: true
)
- Real-time suggestions appear as you type
- No Enter key required - suggestions show instantly
- Debounced for performance - optimized for smooth typing
- Smart relevance sorting - exact matches first, then starts-with, then contains
- Auto-clear functionality - click X to clear selection
Dropdown Mode (useAutocomplete: false
)
- Traditional dropdown with search functionality inside
- Click to open dropdown with search box
- Keyboard navigation support
- More familiar UX for users expecting dropdowns
Widget Parameters
Parameter | Type | Description |
---|---|---|
useAutocomplete |
bool |
Enable autocomplete mode (true) or dropdown mode (false). Default: true |
showCountry |
bool |
Show country picker. Default: true |
showState |
bool |
Show state picker. Default: true |
showCity |
bool |
Show city picker. Default: true |
countryHint |
String? |
Hint text for country field |
stateHint |
String? |
Hint text for state field |
cityHint |
String? |
Hint text for city field |
theme |
LocationPickerTheme? |
Custom theme for styling |
onCountryChanged |
Function(CountryModel?)? |
Callback when country is selected |
onStateChanged |
Function(StateModel?)? |
Callback when state is selected |
onCityChanged |
Function(CityModel?)? |
Callback when city is selected |
Models
CountryModel
CountryModel(
id: '1',
sortName: 'US',
name: 'United States',
phoneCode: '1',
flagEmoji: 'πΊπΈ',
capital: 'Washington, D.C.',
currency: 'USD',
)
StateModel
StateModel(
id: '1',
name: 'California',
countryId: '1',
stateCode: 'CA',
type: 'State',
)
CityModel
CityModel(
id: '1',
name: 'Los Angeles',
stateId: '1',
latitude: '34.0522',
longitude: '-118.2437',
isCapital: false,
)
π LocationModel (Live Location)
LocationModel(
latitude: 34.0522,
longitude: -118.2437,
address: '123 Main St, Los Angeles, CA 90210, USA',
street: '123 Main St',
locality: 'Los Angeles', // City
administrativeArea: 'CA', // State
country: 'United States',
postalCode: '90210',
countryCode: 'US',
)
π₯ LocationResult (NEW v2.1.0 - Unified Widget)
LocationResult(
latitude: 34.0522,
longitude: -118.2437,
address: '123 Main St, Los Angeles, CA 90210, USA',
city: 'Los Angeles',
state: 'California',
country: 'United States',
postalCode: '90210',
addressSource: AddressSource.googlePlaces, // googlePlaces, manualEntry, or gpsLocation
)
AddressSource Enum
enum AddressSource {
googlePlaces, // Address selected from Google Places dropdown
manualEntry, // User manually entered address
gpsLocation, // Address detected from GPS coordinates
}
π₯ LocationPickerPlusUnifiedWidget Parameters (NEW v3.0.0)
Parameter | Type | Description |
---|---|---|
mode |
LocationPickerMode |
Widget mode: googlePlaces , currentLocation , manualEntry , or all . Default: all |
googlePlacesApiKey |
String? |
Google Places API key for address search |
allowedCountries |
List<String>? |
Restrict countries in dropdown (names or ISO codes like ['IN', 'US'] ) |
lockFieldsForGooglePlaces |
bool |
Lock manual entry fields when Google Places address is selected. Default: true |
onLocationSelected |
Function(LocationResult?)? |
Called when location is selected from any source |
country |
String? |
Restrict Google Places to specific country (ISO code) |
placesTypes |
List<String> |
Google Places types filter. Default: [] |
placesHintText |
String |
Google Places search hint. Default: 'Search for a place...' |
useDropdownsForCountryState |
bool |
Use dropdowns for country/state in manual entry. Default: true |
autoDetectOnInit |
bool |
Auto-detect GPS location on widget load. Default: false |
showCoordinates |
bool |
Show coordinates in location display. Default: true |
theme |
LocationPickerTheme? |
Custom theme for styling |
π LocationDetectorWidget Parameters
Parameter | Type | Description |
---|---|---|
mode |
LocationDetectorMode |
Detection mode: currentLocation , addressSearch , or both |
showCoordinates |
bool |
Show latitude/longitude in results. Default: true |
showFullAddress |
bool |
Show complete address breakdown. Default: true |
autoDetectOnInit |
bool |
Auto-detect location on widget load. Default: false |
accuracy |
LocationAccuracy |
GPS accuracy level. Default: LocationAccuracy.high |
timeLimit |
Duration? |
Max time to wait for location. Default: null |
currentLocationLabel |
String |
Label for GPS button. Default: 'Current Location' |
addressSearchLabel |
String |
Label for search field. Default: 'Search Address' |
addressSearchHint |
String? |
Placeholder for search field |
theme |
LocationPickerTheme? |
Custom theme for styling |
onLocationChanged |
Function(LocationModel?)? |
Called when location is detected/searched |
onAddressChanged |
Function(String)? |
Called when address changes |
onCoordinatesChanged |
Function(double, double)? |
Called when coordinates change |
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License.
Libraries
- location_picker_plus
- location_picker_plus_method_channel
- location_picker_plus_platform_interface
- location_picker_plus_web
- models/city_model
- models/country_model
- models/location_model
- models/location_result
- models/state_model
- services/google_places_service
- services/location_detector_service
- services/location_service
- themes/enhanced_location_theme
- themes/location_picker_plus_theme
- utils/adaptive_debouncer
- widgets/autocomplete_dropdown
- widgets/enhanced_google_places_widget
- widgets/google_places_autocomplete_widget
- widgets/location_detector_widget
- widgets/location_picker_plus_unified_widget
- widgets/location_picker_plus_widget
- widgets/manual_address_entry_widget
- widgets/multi_field_places_widget
- widgets/virtual_dropdown_list