Google Places Autocomplete

Flutter 3.24+ pub package License: MIT

A powerful, UI-agnostic Flutter package for Google Places API integration. Get autocomplete predictions with distance from user, detailed place information, and full control over your UI.

✨ Features

  • 🎨 UI-Agnostic - Bring your own UI, we handle the data
  • 📍 Distance Support - Show distance from user to each prediction
  • 🔐 Platform-Native API Keys - Read from AndroidManifest/Info.plist (no hardcoded keys!)
  • 🌍 Cross-Platform - Android, iOS
  • Performance Optimized - Built-in debouncing
  • 🔧 Highly Configurable - Filter by country, place type, language

🚀 Quick Start

1. Platform Setup

Android - Add to AndroidManifest.xml:

<application>
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="YOUR_API_KEY" />
</application>

iOS - Add to Info.plist:

<key>GOOGLE_PLACES_API_KEY</key>
<string>YOUR_API_KEY</string>

2. Install

dependencies:
  google_places_autocomplete: ^1.0.0

3. Use

import 'package:google_places_autocomplete/google_places_autocomplete.dart';

final places = GooglePlacesAutocomplete(
  // Optional - reads from platform config if not provided
  // apiKey: 'YOUR_KEY',
  
  // Optional - enables distance display in predictions
  originLat: userLatitude,
  originLng: userLongitude,
  
  predictionsListener: (predictions) {
    for (final p in predictions) {
      print('${p.title} - ${p.distanceMeters}m away');
    }
  },
  loadingListener: (isLoading) => print('Loading: $isLoading'),
);

await places.initialize();  // Important: await this!
places.getPredictions('coffee shop');

📖 API Reference

Constructor Parameters

Parameter Type Required Description
predictionsListener Function(List<Prediction>) Callback for predictions
loadingListener Function(bool) Loading state callback
apiKey String? API key (uses platform config if null)
originLat double? User latitude for distance calculation
originLng double? User longitude for distance calculation
debounceTime int Debounce in ms (default: 300, min: 200)
countries List<String>? Country codes e.g. ['us', 'ca']
primaryTypes List<String>? Place types e.g. ['restaurant']
language String? Language code e.g. 'en'

Methods

// Initialize (required, async)
await places.initialize();

// Get predictions
places.getPredictions('search query');

// Get place details
final details = await places.getPredictionDetail('place_id');

// Update user location (for distance)
places.setOrigin(latitude: 37.7749, longitude: -122.4194);

// Clear origin (disable distance)
places.clearOrigin();

Prediction Model

class Prediction {
  final String? placeId;       // Use with getPredictionDetail()
  final String? title;         // Main text
  final String? description;   // Secondary text
  final int? distanceMeters;   // Distance from origin (if set)
  final List<String>? types;   // Place types
}

PlaceDetails Model

class PlaceDetails {
  final String? name;
  final String? formattedAddress;
  final Location? location;        // .lat, .lng
  final String? nationalPhoneNumber;
  final String? internationalPhoneNumber;
  final String? googleMapsUri;
  final String? websiteUri;
  // ... and more
}

💡 Examples

Display Distance Badge

ListTile(
  title: Text(prediction.title ?? ''),
  subtitle: Text(prediction.description ?? ''),
  trailing: prediction.distanceMeters != null
      ? Text(_formatDistance(prediction.distanceMeters!))
      : null,
);

String _formatDistance(int meters) {
  if (meters >= 1000) {
    return '${(meters / 1000).toStringAsFixed(1)} km';
  }
  return '$meters m';
}

Filter by Country

GooglePlacesAutocomplete(
  countries: ['pk', 'ae'],  // Pakistan & UAE only
  predictionsListener: (p) => setState(() => predictions = p),
);

Get Coordinates from Selection

onTap: () async {
  final details = await places.getPredictionDetail(prediction.placeId!);
  final lat = details?.location?.lat;
  final lng = details?.location?.lng;
  // Use coordinates...
}

⚠️ Breaking Changes (v0.1.1)

Change Before After
Listener names predictionsListner predictionsListener
loadingListner loadingListener
Initialize initialize() (sync) await initialize() (async)
API key Required Optional (platform fallback)

🔧 Troubleshooting

Issue Solution
No predictions Ensure Places API is enabled in Google Cloud Console
No distance shown Provide originLat and originLng
API key not found Check platform manifest/plist configuration

📄 License

MIT License - see LICENSE for details.