Flutter地点自动完成插件google_places_autocomplete的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter地点自动完成插件 google_places_autocomplete 的使用

google_places_autocomplete 是一个用于在Flutter应用中集成Google Places API的包。它提供了地点自动完成功能,支持获取详细地点信息,并且具有灵活的UI设计。

功能

  • 自动完成搜索并提供预测和建议。
  • 获取详细地点信息(地址、电话号码、地理坐标等)。
  • 支持按国家、地点类型和语言过滤结果。
  • 提供防抖功能以提高性能和用户体验。
  • google_maps_flutter 集成,实现无缝的地图交互。

开始使用

前提条件

  1. 在Google Cloud Platform上创建一个项目,并启用Places API(new)
  2. 获取访问Places API的API密钥。可以通过Google API文档获取。

安装

pubspec.yaml 文件中添加以下内容:

dependencies:
  google_places_autocomplete: latest_version

然后运行:

flutter pub get

使用

基本设置

  1. 导入包:

    import 'package:google_places_autocomplete/google_places_autocomplete.dart';
    
  2. 初始化服务:

    final googlePlaces = GooglePlacesAutocomplete(
      apiKey: "YOUR_API_KEY",
      predictionsListner: (predictions) {
        // 处理预测结果
      },
      debounceTime: 300, // 自定义防抖时间
      countries: ['us'], // 限制为美国
      primaryTypes: ['locality'], // 关注特定类型
    );
    
    googlePlaces.initialize();
    
  3. 获取预测结果:

    googlePlaces.getPredictions("San Francisco");
    

    或者直接传递给TextField的 onChanged 参数:

    TextFormField(
        controller: textEditingController,
        focusNode: focusNode,
        onChanged: googlePlaces.getPredictions,
    )
    
  4. 获取地点详情:

    final placeDetails = await googlePlaces.getPredictionDetail("PLACE_ID");
    print(placeDetails?.formattedAddress);
    

示例代码

以下是一个将Google Places Autocomplete与Flutter TextField小部件集成的示例:

import 'package:flutter/material.dart';
import 'package:google_places_autocomplete/google_places_autocomplete.dart';

class PlaceSearchScreen extends StatefulWidget {
  @override
  _PlaceSearchScreenState createState() => _PlaceSearchScreenState();
}

class _PlaceSearchScreenState extends State<PlaceSearchScreen> {
  late final GooglePlacesAutocomplete _placesAutocomplete;

  @override
  void initState() {
    super.initState();
    _placesAutocomplete = GooglePlacesAutocomplete(
      apiKey: "YOUR_API_KEY",
      predictionsListner: (predictions) {
        // 处理预测结果并更新UI
      },
    );
    _placesAutocomplete.initialize();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Search Places")),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              decoration: InputDecoration(labelText: "Search Location"),
              onChanged: (value) => _placesAutocomplete.getPredictions(value),
            ),
            // 添加显示预测结果和处理交互的小部件
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _placesAutocomplete.dispose();
    super.dispose();
  }
}

更详细的示例

以下是更完整的示例,展示了如何从用户输入中获取预测结果,并在选择某个预测时获取详细地点信息:

import 'package:flutter/material.dart';
import 'package:google_places_autocomplete/google_places_autocomplete.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Google Places Autocomplete Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const PlacesAutocompleteScreen(),
    );
  }
}

class PlacesAutocompleteScreen extends StatefulWidget {
  const PlacesAutocompleteScreen({super.key});

  @override
  PlacesAutocompleteScreenState createState() => PlacesAutocompleteScreenState();
}

class PlacesAutocompleteScreenState extends State<PlacesAutocompleteScreen> {
  final TextEditingController _searchController = TextEditingController();

  /// The Google Places API key (replace with your actual API key).
  final String _apiKey = 'GOOGLE_PLACES_API_KEY';

  /// The autocomplete service instance.
  late GooglePlacesAutocomplete _placesService;

  /// List to store predictions for display.
  List<Prediction> _predictions = [];

  /// Details of the selected place.
  PlaceDetails? _placeDetails;

  @override
  void initState() {
    super.initState();

    // Initialize the GooglePlacesAutocomplete service.
    _placesService = GooglePlacesAutocomplete(
      apiKey: _apiKey,
      debounceTime: 300,
      predictionsListner: (predictions) {
        setState(() {
          _predictions = predictions;
        });
      },
    );

    // Start the service.
    _placesService.initialize();
  }

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }

  /// Fetches details of the selected place using its placeId.
  Future<void> _fetchPlaceDetails(String placeId) async {
    final details = await _placesService.getPredictionDetail(placeId);
    setState(() {
      _placeDetails = details;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Google Places Autocomplete'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // Search input field
            TextField(
              controller: _searchController,
              decoration: const InputDecoration(
                hintText: 'Search for a place',
                border: OutlineInputBorder(),
                suffixIcon: Icon(Icons.search),
              ),
              onChanged: (value) {
                // Fetch predictions as the user types.
                _placesService.getPredictions(value);
              },
            ),
            const SizedBox(height: 16),

            // Display predictions
            Expanded(
              child: ListView.builder(
                itemCount: _predictions.length,
                itemBuilder: (context, index) {
                  final prediction = _predictions[index];
                  return ListTile(
                    title: Text('${prediction.title}'),
                    subtitle: Text('${prediction.description}'),
                    onTap: () {
                      // Fetch place details when a prediction is tapped.
                      if (prediction.placeId != null) {
                        _fetchPlaceDetails(prediction.placeId!);
                      }
                    },
                  );
                },
              ),
            ),

            // Display place details if available
            if (_placeDetails != null)
              Padding(
                padding: const EdgeInsets.only(top: 16.0),
                child: Card(
                  elevation: 4.0,
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        if (_placeDetails!.formattedAddress != null)
                          Text("Address: ${_placeDetails!.formattedAddress!}"),
                        if (_placeDetails!.nationalPhoneNumber != null)
                          Text("Phone: ${_placeDetails!.nationalPhoneNumber!}"),
                        if (_placeDetails!.location != null)
                          Text("Location: ${_placeDetails!.location!.toMap()}"),
                      ],
                    ),
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}

以上示例展示了如何使用 google_places_autocomplete 包来实现地点自动完成功能,并展示预测结果和详细地点信息。请确保替换 "YOUR_API_KEY" 为您自己的Google Places API密钥。


更多关于Flutter地点自动完成插件google_places_autocomplete的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地点自动完成插件google_places_autocomplete的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用google_places_autocomplete插件来实现地点自动完成的示例代码。这个插件可以帮助用户通过输入部分地址或地点名称来快速选择具体的地点。

首先,确保你已经在pubspec.yaml文件中添加了google_places_autocomplete依赖:

dependencies:
  flutter:
    sdk: flutter
  google_places_autocomplete: ^2.1.1  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你需要在Android和iOS项目中配置Google Places API。

Android配置

  1. android/app/src/main/AndroidManifest.xml中添加以下权限和API密钥:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yourapp">

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

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

YOUR_GOOGLE_PLACES_API_KEY替换为你的Google Places API密钥。

iOS配置

  1. ios/Runner/Info.plist中添加NSLocationWhenInUseUsageDescription权限(如果需要位置服务):
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location when in use</string>
  1. ios/Runner/AppDelegate.swift中配置API密钥(虽然iOS通常通过环境变量或GoogleService-Info.plist管理API密钥,但这里为简单起见,直接在代码中设置):
import UIKit
import Flutter
import GooglePlaces

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GMSServices.provideAPIKey("YOUR_GOOGLE_PLACES_API_KEY")
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

同样,将YOUR_GOOGLE_PLACES_API_KEY替换为你的Google Places API密钥。

Flutter代码实现

在你的Flutter项目中,创建一个页面来使用google_places_autocomplete插件:

import 'package:flutter/material.dart';
import 'package:google_places_autocomplete/google_places_autocomplete.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Google Places Autocomplete Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PlaceSearchPage(),
    );
  }
}

class PlaceSearchPage extends StatefulWidget {
  @override
  _PlaceSearchPageState createState() => _PlaceSearchPageState();
}

class _PlaceSearchPageState extends State<PlaceSearchPage> {
  final _key = GlobalKey<FormState>();
  String _selectedPlace = '';

  Future<Null> _selectPlace(BuildContext context) async {
    try {
      PlaceResult result = await showSearch(
        context: context,
        delegate: PlacesSearchDelegate(),
      );

      if (result != null) {
        setState(() {
          _selectedPlace = result.fullAddress;
        });
      }
    } catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Google Places Autocomplete Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(
                labelText: 'Search for a place',
                suffixIcon: IconButton(
                  icon: Icon(Icons.search),
                  onPressed: () => _selectPlace(context),
                ),
              ),
            ),
            SizedBox(height: 20),
            if (_selectedPlace.isNotEmpty)
              Text(
                'Selected Place: $_selectedPlace',
                style: TextStyle(fontSize: 18),
              ),
          ],
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个搜索栏。当用户点击搜索图标时,会弹出一个搜索对话框,允许用户选择地点。选择的地点将显示在搜索栏下方。

请确保你已经正确设置了Google Places API,并且API密钥具有适当的权限(如Places API Web Service)。如果你遇到任何问题,检查API密钥的状态、项目配置和API权限。

回到顶部