【问题标题】:Programmatically Select Marker to Navigate To Location Google_Maps_Flutter以编程方式选择标记以导航到位置 Google_Maps_Flutter
【发布时间】:2021-04-10 23:38:59
【问题描述】:

我正在尝试开发一种用户体验,为用户提供旅行地点列表,并在选择其中一个地点时,我希望它能够

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

我能够使用from this PR 的信息(似乎没有官方文档)从这里开始:

到这里:

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

我希望在列表底部选择场地,以便一键自动在第三张图像中显示所有三个标准。也就是说,再一次:

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

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

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

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

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));
});

}

现在,我的解决方案确实添加了标记并显示了信息窗口,但出现了简短的为用户提供导航到位置的选项除非用户单击标记。在目前的状态下,我已经构建了一些可以提供非常次优的用户体验的东西。

我尝试过像highlighting the marker 这样的替代解决方案,但它并没有我想要的功能。我不明白在“选择”点击标记的插件中发生了什么事件,并且我发现“以编程方式”选择标记的所有尝试都会突出显示它。只需提供一些关于在单击标记时查找正在启动的事件的位置的指示会很有帮助。

【问题讨论】:

  • 我真的不相信您可以以编程方式模拟标记的“点击” - 它只会响应用户的物理“点击”。而且,你能以编程方式让小方向/打开地图图标弹出吗?我也不相信你能做到这一点(至少,地图控制器或标记对象上肯定没有可用的方法来做到这一点)——我想这只是地图功能的固有部分。也许您最好在列表顶部(地图下方)有一个“在地图中打开”按钮,用户可以点击该按钮(如果他们实际上没有突出显示标记)
  • 有几个不同的“地图启动器”颤振插件(我已经成功使用了这个pub.dev/packages/maps_launcher)。我和你在同一条船上,我想在 Flutter 中尝试和实现一些不同的事情——非常接近最终目标,然后就是你无法克服的最后一个障碍...... ...无论如何尝试在颤振社区/github中发布问题 - 人们总是非常敏感和乐于助人 - 但我能找到的所有问题都像你问的那样,都说它无法完成
  • 非常感谢您的反馈!老实说,我非常气馁,因为这篇文章被严重否决了。我不知道还有什么方法可以问我在寻找什么,或者如何完成我想做的事情。我最终重新设计了我的用户体验 - 我做到了完全如你所描述的那样。如果您有兴趣,我计划用我的答案来回答这个问题!我的整个颤振之旅正是你所描述的,所以很高兴听到其他人也能感同身受。我也会查看 Flutter 社区/github - 谢谢!
  • 这很酷。抱歉我帮不上忙(但很高兴我能帮上一点忙!):)

标签: flutter google-maps dart google-maps-flutter


【解决方案1】:

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

  1. 据我所知,在 Flutter 中没有办法模拟标记的“点击”。我尝试查看the Kotlin/Swift APIs for platform channels 来自己编写其中的一些功能,但老实说,它离我的驾驶室还很远,我花了很多时间在上面。这也可能导致我必须与 Google 的好人一起通过审批流程才能接受我的更改,但现在不是我个人的时间。

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

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

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

看起来像这样:

现在是用户:

  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),
              ));
            },
          ))

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

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

【讨论】:

    【解决方案2】:

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

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

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

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

     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';
        }
      }
    

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

    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};
              },
            ),
          ],
        );
      }
    

    然后将自定义小部件放入带有Googlemap() 小部件的Stack 小部件

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

    【讨论】:

    • 感谢您分享您的答案!我很高兴其他人得出了类似的结论,希望我们的共同努力能够帮助遇到问题的人:D。
    猜你喜欢
    • 2015-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 2017-06-09
    • 2011-09-03
    • 2013-01-17
    相关资源
    最近更新 更多