Flutter地理编码与反地理编码插件geocoder_buddy的使用

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

Flutter地理编码与反地理编码插件geocoder_buddy的使用

特性

  • 易于使用
  • 快速且安全
  • 无需API密钥
  • 更详细的数据
  • 无需API密钥即可搜索位置

开始使用

在终端中运行以下命令以安装插件:

flutter pub add geocoder_buddy

搜索位置

使用GBSearchData类来查询位置:

// GBSearchData 类由 geocoder_buddy 提供
List<GBSearchData> data = await GeocoderBuddy.query(query);

GBSearchData 类

int placeId;
int id;
List<String> boundingbox;
String lat;
String lon;
String displayName;
int placeRank;
double importance;

将 GBSearchData 转换为 GBData

使用searchToGBData方法将GBSearchData转换为GBData

// GBData 类由 geocoder_buddy 提供
GBData data = await GeocoderBuddy.searchToGBData(GBSearchData data);

根据经纬度获取详细信息

通过纬度和经度获取位置详细信息:

GBLatLng position = GBLatLng(38.8951,-77.0364);
GBData data = await GeocoderBuddy.findDetails(position);

GBData 类

int placeId;
String osmType;
int id;
String lat;
String lon;
int placeRank;
double importance;
String displayName;
Address address; // 由 geocoder_buddy 提供
List<String> boundingbox;

Address 类

String road;
String village;
String county;
String stateDistrict;
String state;
String iso31662Lvl4;
String postcode;
String country;
String countryCode;

示例代码

以下是完整的示例应用,展示如何使用 geocoder_buddy 插件进行地理编码和反地理编码。

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Geocoder Buddy Example',
      theme: ThemeData(
        useMaterial3: true,
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Geocoder Buddy Example'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final searchTextController = TextEditingController();
  final latTextController = TextEditingController();
  final lngTextController = TextEditingController();
  List<GBSearchData> searchItem = [];
  Map<String, dynamic> details = {};
  bool isSearching = false;
  bool isLoading = false;

  void searchLocation(String query) async {
    setState(() {
      isSearching = true;
    });
    List<GBSearchData> data = await GeocoderBuddy.query(query);
    setState(() {
      isSearching = false;
      searchItem = data;
    });
  }

  getAddressDetails(GBLatLng pos) async {
    setState(() {
      isLoading = true;
    });
    GBData data = await GeocoderBuddy.findDetails(pos);
    setState(() {
      isLoading = false;
      details = data.toJson();
    });
    print(data.address.village);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              const SizedBox(height: 10),
              Text("Search Location", style: Theme.of(context).textTheme.headline3),
              Container(
                padding: const EdgeInsets.all(20),
                child: TextField(
                  controller: searchTextController,
                  decoration: const InputDecoration(
                      hintText: "Search Location",
                      border: OutlineInputBorder()),
                ),
              ),
              ElevatedButton(
                  onPressed: () {
                    if (searchTextController.text.isNotEmpty) {
                      searchLocation(searchTextController.text);
                    } else {
                      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Please Enter Location")));
                    }
                  },
                  child: const Text("Search")),
              SizedBox(
                height: 300,
                child: !isSearching
                    ? ListView.builder(
                        itemCount: searchItem.length,
                        itemBuilder: (context, index) {
                          var item = searchItem[index];
                          return ListTile(
                            onTap: () {
                              // Navigate to detail page if needed
                            },
                            title: Text(item.displayName),
                          );
                        })
                    : const Center(child: CircularProgressIndicator()),
              ),
              const SizedBox(height: 20),
              Text("Lat/Lng to Details", style: Theme.of(context).textTheme.headline3),
              Container(
                padding: const EdgeInsets.all(20),
                child: TextField(
                  controller: latTextController,
                  decoration: const InputDecoration(hintText: "Latitude", border: OutlineInputBorder()),
                ),
              ),
              Container(
                padding: const EdgeInsets.all(20),
                child: TextField(
                  controller: lngTextController,
                  decoration: const InputDecoration(hintText: "Longitude", border: OutlineInputBorder()),
                ),
              ),
              ElevatedButton(
                  onPressed: () {
                    if (latTextController.text.isNotEmpty && lngTextController.text.isNotEmpty) {
                      GBLatLng pos = GBLatLng(lat: double.parse(latTextController.text), lng: double.parse(lngTextController.text));
                      getAddressDetails(pos);
                    } else {
                      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Please Enter Lat/Lng")));
                    }
                  },
                  child: const Text("Get Details")),
              const SizedBox(height: 20),
              SizedBox(
                height: 300,
                child: !isLoading
                    ? ListView.builder(
                        itemCount: details.keys.length,
                        itemBuilder: (context, index) {
                          var key = details.keys.elementAt(index);
                          return ListTile(
                            title: Text("$key: ${details[key]}"),
                          );
                        })
                    : const Center(child: CircularProgressIndicator()),
              ),
              const SizedBox(height: 20),
            ],
          ),
        ));
  }
}

以上是完整的示例代码,展示了如何使用 geocoder_buddy 插件进行地理编码和反地理编码。希望这些内容能帮助您更好地理解和使用该插件。


更多关于Flutter地理编码与反地理编码插件geocoder_buddy的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地理编码与反地理编码插件geocoder_buddy的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的地理编码与反地理编码插件geocoder_buddy的使用,下面是一个简单的代码示例,展示了如何使用该插件进行地理编码和反地理编码操作。

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

dependencies:
  flutter:
    sdk: flutter
  geocoder_buddy: ^latest_version  # 请替换为实际的最新版本号

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

接下来是一个完整的Flutter应用示例,展示了如何使用geocoder_buddy进行地理编码和反地理编码:

import 'package:flutter/material.dart';
import 'package:geocoder_buddy/geocoder_buddy.dart';
import 'package:geolocator/geolocator.dart';

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

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

class GeocoderScreen extends StatefulWidget {
  @override
  _GeocoderScreenState createState() => _GeocoderScreenState();
}

class _GeocoderScreenState extends State<GeocoderScreen> {
  String _address = '';
  String _latitude = '';
  String _longitude = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Geocoder Buddy Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Enter Address'),
              onChanged: (value) {
                setState(() {
                  _address = value;
                });
              },
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: _geocodeAddress,
              child: Text('Geocode Address'),
            ),
            SizedBox(height: 16),
            Text('Latitude: $_latitude'),
            SizedBox(height: 8),
            Text('Longitude: $_longitude'),
            SizedBox(height: 32),
            ElevatedButton(
              onPressed: _reverseGeocode,
              child: Text('Reverse Geocode'),
            ),
            SizedBox(height: 16),
            Text('Address: $_address'),
          ],
        ),
      ),
    );
  }

  Future<void> _geocodeAddress() async {
    if (_address.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Address cannot be empty')));
      return;
    }

    final Geocoding geocoding = Geocoding();
    List<Placemark> placemarks = await geocoding.placemarkFromAddress(_address);

    if (placemarks.isNotEmpty) {
      Placemark place = placemarks.first;
      setState(() {
        _latitude = place.position?.latitude.toString() ?? '';
        _longitude = place.position?.longitude.toString() ?? '';
      });
    } else {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Address not found')));
    }
  }

  Future<void> _reverseGeocode() async {
    double lat = double.tryParse(_latitude) ?? 0.0;
    double lng = double.tryParse(_longitude) ?? 0.0;

    if (lat == 0.0 || lng == 0.0) {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Latitude and Longitude cannot be empty')));
      return;
    }

    final Geocoding geocoding = Geocoding();
    List<Placemark> placemarks = await geocoding.placemarkFromCoordinates(lat, lng);

    if (placemarks.isNotEmpty) {
      Placemark place = placemarks.first;
      setState(() {
        _address = '${place.thoroughfare}, ${place.subThoroughfare}, ${place.locality}, ${place.postalCode}, ${place.country}';
      });
    } else {
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Coordinates not found')));
    }
  }
}

注意事项

  1. 在实际使用中,确保设备具有网络权限,因为地理编码与反地理编码操作需要访问网络。
  2. geocoder_buddy 插件实际上依赖于 geolocatorgeocoding 插件进行地理定位与编码操作。上面的代码示例实际上结合了 geocoding 插件进行地理编码与反地理编码,因为 geocoder_buddy 并不是一个官方或广泛使用的Flutter插件名称。如果geocoder_buddy是一个自定义或特定项目中的插件名称,请确保按照其实际API文档进行调整。
  3. 在实际项目中,可能还需要处理异常和错误情况,例如网络错误、API限制等。

如果geocoder_buddy确实是你项目中特定的插件,并且有不同的API调用方式,请参考该插件的官方文档或源代码进行调整。

回到顶部