以编程方式选择标记以导航到位置 Google_Maps_Flutter

kal*_*les 7 google-maps dart flutter google-maps-flutter

我正在尝试开发一种用户体验,向用户提供要前往的地点列表,并在选择其中一个地点后,我希望它能够

  1. 向地图添加标记
  2. 显示信息窗口
  3. 提供导航到该位置的选项。

我能够使用此 PR 中的信息(似乎没有官方文档)来进行以下操作:

使用 PR 之前

对此:

使用 showMarkerInfo 函数后的功能

但是,显示标记信息仍然不会使给定标记“活动”。当我选择标记时,插件的功能实际上会在右下角显示用于导航到给定位置的选项,如下所示:

实际选择标记时 Google_Maps_Flutter 插件的功能。

我想要的是列表底部的场地选择只需按一下即可自动显示第三张图像中的所有三个标准。也就是说,再一次:

  1. 位置的标记
  2. 信息窗口
  3. 导航到该位置的选项。

现在,用户必须单击底部列表中的条目,然后非常不直观地单击地图上的标记才能显示导航选项。

当用户从列表中选择项目时“点击”标记时,我将如何以编程方式启动“点击”事件?

这是我当前用于更改视口、添加标记和显示信息窗口的代码:

Future<void> goSomewhere(id, name, distance, address, lat, lng) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
    CameraPosition(target: LatLng(lat, lng), zoom: 14.0)));
setState(() {
  _markers.add(Marker(
    markerId: MarkerId(id),
    position: LatLng(lat, lng),
    infoWindow: InfoWindow(
      title: name,
      snippet: address,
    ),
    onTap: () {
      //_pageController.jumpToPage(i);
    },
    icon: BitmapDescriptor.defaultMarker,
  ));
  print(MarkerId(id));
  controller.showMarkerInfoWindow(MarkerId(id));
});
Run Code Online (Sandbox Code Playgroud)

}

现在,我的解决方案确实添加了标记并显示信息窗口,但无法为用户提供导航到该位置的选项,除非用户单击标记。在目前的状态下,我构建的东西带来了非常次优的用户体验。

我尝试过其他解决方案,例如突出显示标记,但它并不完全具有我正在寻找的功能。我不明白在点击时“选择”标记的插件中发生了什么事件,并且我发现“以编程方式”选择标记的所有尝试都做了某种版本的突出显示。简单地指示在单击标记时在哪里查找正在启动的事件将会有所帮助。

kal*_*les 10

我没有得出完整的答案,但我想分享我的经验,以防其他人遇到这个问题并感到困惑。通过浏览 Flutter Github/在论坛上询问,我得到了三个关键要点:

  1. 据我所知,Flutter中没有办法模拟标记的“点击”。我尝试查看平台通道的 Kotlin/Swift API 来自己编写一些此功能,但说实话,这远远超出了我的能力范围,我在上面浪费了很多时间。这也可能导致我必须与谷歌的好人一起完成审批流程才能接受我的更改,但我个人现在还不是时候。

  2. 我发现了一个名为Maps Launcher 的软件包,Craig 在评论部分也提到了它,它能够通过两种方法启动地图应用程序 - 通过查询启动和通过纬度/经度启动。此功能实际上与您点击标记然后选择右下角的两个地图选项之一时获得的功能相同。

  3. 我发现点击标记时获得的两个图标之间的主要区别在于,一个通过查询启动方向,另一个通过纬度和经度启动 - 就像地图启动器插件一样。

因此,利用这三条信息,我重新设计了应用程序:

原创体验

看起来像这样:

MAP 启动器的新体验

现在是用户:

  1. 从列表中选择一个位置。
  2. 选择新位置会添加标记并显示该位置的信息窗口
  3. 可以点击右侧的按钮导航到给定的位置。

在我看来,这种体验更加清晰 - 选择标记时可以启动的两个地图选项(通过查询与纬度/经度)之间没有任何歧义,因为启动地图图标的按钮现在位于列表视图上。这还允许您非常轻松地导航到每个标记,只需在列表视图中单击它,然后通过按右侧的按钮决定是否需要导航方向。

将其添加到您的应用程序的代码非常简单:

new Flexible(
            child: ListView.builder(
            itemCount: venues.length,
            padding: EdgeInsets.all(4.0),
            itemBuilder: (context, index) {
              return Card(
                  color: _selectedIndex != null && _selectedIndex == index
                      ? Colors.greenAccent
                      : Colors.white,
                  child: ListTile(
                onTap: () {
                  goSomewhere(
                      venues[index].venueId,
                      venues[index].name,
                      venues[index].distance,
                      venues[index].formattedAddress,
                      double.parse(venues[index].latitude),
                      double.parse(venues[index].longitude)
                  );
                  _onSelected(index);
                },
                title: Text(
                  venues[index]
                      .name /*+ ' and ' + venues[index].formattedAddress*/,
                  style: TextStyle(fontWeight: FontWeight.w500),
                ),
                trailing: Container(
                    child: ElevatedButton(
                  style: ElevatedButton.styleFrom(
                    primary: Colors.blue,

                  ),
                      onPressed: () => MapsLauncher.launchQuery(
                          venues[index].formattedAddress),
                      child: Icon(Icons.assistant_navigation),
                )),
                subtitle: Text(venues[index].formattedAddress),
              ));
            },
          ))
Run Code Online (Sandbox Code Playgroud)

这是一个微妙的差异,但我已经做了一些测试,我的(一小群)用户似乎更喜欢这个,因为它更直观。此外,无论他们按下哪个按钮,他们在地图应用程序中获得的位置都有一个可识别的地址。

虽然这不是对原始问题的“完整”答案,但我希望这可以帮助人们在 Flutter 之旅中坚持使用该框架 - 尽管存在一些早期障碍。


Nel*_*Jr. 7

你打败了我!我本来想回答这个问题,但当我重新加载页面时,我看到你已经回答了。尽管您似乎已经找到了问题的解决方案,但我仍然想在这里发布我的答案。请看下面:

我找不到以编程方式显示地图工具栏(用于导航到右下角给定位置的选项)的方法,因为您确实需要单击标记来显示它。但我认为这是适合您的用例的解决方法:

  1. mapToolbarEnabled: false通过在小部件中设置禁用地图工具栏GoogleMap()。(无论如何,地图工具栏仅适用于Android)
  2. 创建一个自定义地图工具栏,可从应用程序启动Google 地图路线URL。仅当您从列表视图中选择位置或单击标记时,该工具栏才会显示。

我使用url_launcher包来启动 Google 地图和路线 URL。

 Future<void> _launchUrl(bool isDir, double lat, double lon) async {
    String url = 'https://www.google.com/maps/search/?api=1&query=$lat,$lon';

    if (isDir) {
      url = 'https://www.google.com/maps/dir/?api=1&origin=Googleplex&destination=$lat,$lon';
    }

    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }
Run Code Online (Sandbox Code Playgroud)

然后我在自定义地图工具栏小部件上使用了上面的方法

Widget mapToolBar() {
    return Row(
      children: [
        FloatingActionButton(
          child: Icon(Icons.map),
          backgroundColor: Colors.blue,
          onPressed: () {
            _launchUrl(false, {your_lat}, {your_lng})
          },
        ),
        FloatingActionButton(
          child: Icon(Icons.directions),
          backgroundColor: Colors.blue,
          onPressed: () {
            _launchUrl(true, {your_lat}, {your_lng};
          },
        ),
      ],
    );
  }
Run Code Online (Sandbox Code Playgroud)

然后将自定义的widget放到一个带有widgetStack的widget中Googlemap()

Widget build(BuildContext context) {
    return Scaffold(
      body: Column(children: <Widget>[
        Expanded(
          flex: 7,
          child: Stack(children: [
            GoogleMap(
                  .
                  .
                  .
              ),
            mapToolBar()
          ]),
        ),
        _pageViewBuilder(context),
      ]),
    );
  }
Run Code Online (Sandbox Code Playgroud)