Flutter地点选择器插件place_picker_flutter的使用

Flutter地点选择器插件place_picker_flutter的使用

特性

此插件提供了以下功能:

  • 通过动画图钉指示选定的位置。
  • 可以通过拖动地图来选择位置。
  • 可以通过选择一个兴趣点(POI)来选择位置。
  • 可以通过关键词搜索兴趣点。

安装

dependencies: 部分的 pubspec.yaml 文件中,添加以下行:

place_picker_flutter: <最新版本>

使用

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    body: PlacePicker(
      placePickerController: placePickerController,
      iconWidget: SvgPicture.asset(
        "assets/location.svg",
        height: 60,
      ),
      onSelectPlace: onSelectPoi, // 当选择一个POI时的回调函数
      onSearch: onSearch, // 当通过关键词搜索POI时的回调函数
      map: AMapFlutter( // 自定义的地图小部件
        initCameraPosition: cameraPosition,
        logoPosition: UIControlPosition(
          anchor: UIControlAnchor.bottomLeft,
          offset: UIControlOffset(x: 10, y: 10),
        ),
        compassControlEnabled: false,
        scaleControlEnabled: false,
        zoomControlEnabled: false,
        hawkEyeControlEnabled: false,
        mapTypeControlEnabled: false,
        geolocationControlEnabled: false,
        showUserLocation: false,
        onMapCreated: (controller) => aMapController = controller,
        onMapCompleted: refreshNearBy,
        onCameraChange: kIsWeb ? null : onCameraChange,
        onCameraChangeFinish: kIsWeb ? null : onCameraChangeFinish,
        onMapMove: kIsWeb ? onMapMove : null,
        onMapMoveEnd: kIsWeb ? onMapMoveEnd : null,
      ),
    ),
  );
}

PlacePickerController 可以控制地点图钉的上下移动,并且可以刷新地点列表。
iconWidget 可以自定义地点图钉图标。
onSelectPlace 是当从地点列表中选择一个地点时的回调函数。
onSearch 是当通过关键词搜索POI时的回调函数。
map 是自定义的地图小部件以展示地图。

更多详细的使用方法可以参考示例应用。

示例代码

示例代码

import 'package:amap_flutter/amap_flutter.dart';
import 'package:amap_webservice/amap_webservice.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:latlong2/latlong.dart';
import 'package:place_picker_flutter/place_picker_flutter.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

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

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final placePickerController = PlacePickerController();
  final aMapWebService = AMapWebService(
    apiKey: "0e2f6cd577c7b01f2f10e8a8a4cdf153",
    secretKey: "36b5528aecd3e4aba379e1ef352820fd",
  );
  AMapController? aMapController;
  late Future mapInitFuture;

  CameraPosition cameraPosition = CameraPosition(
    position: const LatLng(34.24001, 108.912078),
    zoom: 14,
  );

  [@override](/user/override)
  void initState() {
    super.initState();
    mapInitFuture = initMap();
  }

  Future<void> initMap() async {
    await AMapFlutter.init(
      apiKey: ApiKey(
        iosKey: "a4a1394fe817c2f86a424b897b4a9af4",
        androidKey: "d0065c21d2aedd0b234bfb7b88e5d6b2",
        webKey: "fc9908dc4103f3d8274070bb34ab37af",
      ),
      agreePrivacy: true,
    );
  }

  void refreshNearBy() async {
    LatLng? position = cameraPosition.position;
    if (position != null) {
      final response = await aMapWebService.searchAround(position);
      if (response.pois != null) {
        List<Place> places = [];
        for (var poi in response.pois!) {
          if (poi.id != null && poi.name != null && poi.address != null && poi.location != null) {
            places.add(Place(
              id: poi.id!,
              name: poi.name!,
              address: poi.address!,
              location: poi.location!,
            ));
          }
        }
        placePickerController.refreshPlaces?.call(places);
      }
    }
  }

  Future<List<Place>?> onSearch(String value) async {
    final response = await aMapWebService.textSearch(keywords: value);
    if (response.pois != null) {
      List<Place> places = [];
      for (var poi in response.pois!) {
        if (poi.id != null && poi.name != null && poi.address != null && poi.location != null) {
          places.add(Place(
            id: poi.id!,
            name: poi.name!,
            address: poi.address!,
            location: poi.location!,
          ));
        }
      }
      return places;
    }
    return null;
  }

  void onSelectPoi(Place place) {
    final position = place.location;
    cameraPosition = CameraPosition(
      position: position,
      heading: cameraPosition.heading,
      skew: cameraPosition.skew,
      zoom: cameraPosition.zoom,
    );
    aMapController?.moveCamera(cameraPosition);
  }

  void onCameraChange(CameraPosition position) {
    placePickerController.mapStartMoving!();
    setState(() {
      cameraPosition = position;
    });
  }

  void onCameraChangeFinish(CameraPosition _) {
    placePickerController.mapFinishMoving!();
    refreshNearBy();
  }

  void onMapMove(LatLng latLng) {
    placePickerController.mapStartMoving!();
    setState(() {
      cameraPosition = cameraPosition.copyWith(position: latLng);
    });
  }

  void onMapMoveEnd(LatLng latLng) {
    placePickerController.mapFinishMoving!();
    refreshNearBy();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder(
        future: mapInitFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState != ConnectionState.done) {
            return const Center(child: CircularProgressIndicator());
          } else {
            return Stack(
              alignment: Alignment.topCenter,
              children: [
                PlacePicker(
                  placePickerController: placePickerController,
                  iconWidget: SvgPicture.asset(
                    "assets/location.svg",
                    height: 60,
                  ),
                  onSelectPlace: onSelectPoi,
                  onSearch: onSearch,
                  map: AMapFlutter(
                    initCameraPosition: cameraPosition,
                    logoPosition: UIControlPosition(
                      anchor: UIControlAnchor.bottomLeft,
                      offset: UIControlOffset(x: 10, y: 10),
                    ),
                    compassControlEnabled: false,
                    scaleControlEnabled: false,
                    zoomControlEnabled: false,
                    hawkEyeControlEnabled: false,
                    mapTypeControlEnabled: false,
                    geolocationControlEnabled: false,
                    showUserLocation: false,
                    onMapCreated: (controller) => aMapController = controller,
                    onMapCompleted: refreshNearBy,
                    onCameraChange: kIsWeb ? null : onCameraChange,
                    onCameraChangeFinish: kIsWeb ? null : onCameraChangeFinish,
                    onMapMove: kIsWeb ? onMapMove : null,
                    onMapMoveEnd: kIsWeb ? onMapMoveEnd : null,
                  ),
                ),
                Positioned(
                  top: MediaQuery.of(context).viewPadding.top + 20,
                  child: Container(
                    alignment: Alignment.center,
                    padding: const EdgeInsets.all(10),
                    decoration: BoxDecoration(
                      color: Colors.grey[300]!.withOpacity(0.8),
                      borderRadius: const BorderRadius.all(Radius.circular(10)),
                    ),
                    child: Text(
                      "${cameraPosition.position?.latitude}, "
                      "${cameraPosition.position?.longitude}",
                      style: const TextStyle(fontSize: 16),
                    ),
                  ),
                ),
              ],
            );
          }
        },
      ),
    );
  }
}

更多关于Flutter地点选择器插件place_picker_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter地点选择器插件place_picker_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用place_picker_flutter插件来选择地点的示例代码。

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

dependencies:
  flutter:
    sdk: flutter
  place_picker_flutter: ^最新版本号 # 请替换为当前最新版本号

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

接下来,在你的Dart文件中,你可以按照以下步骤来使用place_picker_flutter插件:

  1. 导入必要的包。
  2. 配置权限(特别是位置权限)。
  3. 使用PlacePicker小部件或相关函数来选择地点。

以下是一个完整的示例:

import 'package:flutter/material.dart';
import 'package:place_picker_flutter/place_picker_flutter.dart';
import 'package:permission_handler/permission_handler.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Place Picker Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PlacePickerScreen(),
    );
  }
}

class PlacePickerScreen extends StatefulWidget {
  @override
  _PlacePickerScreenState createState() => _PlacePickerScreenState();
}

class _PlacePickerScreenState extends State<PlacePickerScreen> {
  PlaceResult? selectedPlace;

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

  Future<void> _requestLocationPermission() async {
    var status = await Permission.location.status;
    if (!status.isGranted) {
      var result = await Permission.location.request();
      if (!result.isGranted) {
        // 权限被拒绝,可以显示一个提示信息
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: Text('权限被拒绝'),
            content: Text('需要位置权限来选择地点'),
            actions: <Widget>[
              TextButton(
                onPressed: () => Navigator.of(context).pop(),
                child: Text('确定'),
              ),
            ],
          ),
        );
      }
    }
  }

  Future<void> _pickPlace() async {
    final result = await PlacePicker().pickPlace(context);

    if (result != null) {
      setState(() {
        selectedPlace = result;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Place Picker'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _pickPlace,
              child: Text('选择地点'),
            ),
            if (selectedPlace != null)
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Text('名称: ${selectedPlace!.name}'),
                    Text('地址: ${selectedPlace!.address}'),
                    Text('纬度: ${selectedPlace!.latitude}'),
                    Text('经度: ${selectedPlace!.longitude}'),
                  ],
                ),
              ),
          ],
        ),
      ),
    );
  }
}

注意事项:

  1. 权限处理:在真实应用中,处理权限请求和用户拒绝权限的情况是非常重要的。上面的示例只是简单地显示了一个对话框,但在生产环境中,你可能需要更复杂的逻辑来处理权限问题。
  2. 依赖项place_picker_flutter插件可能依赖于其他包(如permission_handler)来处理权限请求。确保你添加了所有必要的依赖项。
  3. UI/UX:上面的示例提供了一个基本的UI,你可能需要根据自己的应用需求进行调整。

希望这个示例能帮你更好地使用place_picker_flutter插件!

回到顶部