以编程方式 Select 导航至位置的标记 Google_Maps_Flutter
Programmatically Select Marker to Navigate To Location Google_Maps_Flutter
我正在尝试开发一种用户体验,向用户提供前往的地点列表,并且在select访问其中一个地点后,我希望它
- 在地图上添加标记
- 显示信息window
- 提供导航至
位置。
我能够使用信息 from this PR(似乎没有官方文档)从这里开始:
为此:
但是,显示标记信息仍然不会使给定标记“激活”。当我 select 标记时,插件的功能实际上会显示用于导航到右下角给定位置的选项,如下所示:
我想要的是 select 列表底部的场地离子按一次自动显示第三张图片中的所有三个标准。即再次:
- 位置标记
- 信息window
- 导航到该位置的选项。
现在,用户必须单击底部列表中的条目,然后相当不直观地 单击地图上的标记 才能使用导航选项出现。
我将如何以编程方式启动当用户在 select 从列表中“点击”标记时发生的“点击”事件?
这是我当前用于更改视口、添加标记和显示信息的代码 window:
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));
});
}
现在,我的解决方案确实添加了标记并显示了信息 window,但很快就给用户提供了导航到该位置的选项 ,除非 用户单击标记。在目前的状态下,我构建了一些可以提供非常次优的用户体验的东西。
我已经尝试过 highlighting the marker 等替代解决方案,但它并不完全具备我正在寻找的功能。我不明白插件中发生了什么事件,“selects”标记点击,我发现所有尝试“以编程方式”select 标记做了一些版本的突出显示。简单地说明在单击标记时在哪里查看正在启动的事件会有所帮助。
我没有得出完整的答案,但我想分享我的经验,以防其他人遇到这个问题并感到困惑。通过浏览 Flutter Github / 在论坛中询问,我得到了三个关键要点:
据我所知,Flutter中没有办法模拟marker的“敲击”。我尝试查看 the Kotlin/Swift APIs for platform channels 来自己编写其中的一些功能,但老实说,它离我的驾驶室还很远,我为此浪费了很多时间。这也可能导致必须与 Google 的好人一起完成批准程序才能接受我的更改,但我个人现在还没有时间。
我发现了一个名为 Maps Launcher 的包,Craig 在评论部分也提到了它,它能够通过两种方法启动地图应用程序 - 通过查询启动和通过以下方式启动Latitude/Longitude。此功能实际上与点击标记然后点击右下角的两个地图选项之一 select 时获得的功能相同。
我发现两者的主要区别
点击标记时获得的图标是一个启动
方向查询,另一个方向经纬度 - 只是
比如 Maps Launcher 插件。
因此,根据这三个信息,我重新设计了应用程序:
看起来像这样:
现在是用户:
- 从列表中选择一个位置。
- 选择新位置会添加一个标记并显示该位置的信息窗口
- 可以点击右边的按钮导航到指定位置。
在我看来,这种体验要干净得多 - 在 select 标记时,您可以启动的两个地图选项(通过查询与 lat/long)之间没有歧义,因为启动地图图标的按钮现在位于列表视图上。这也使您可以很容易地导航到每个标记,只需在列表视图中单击它,然后通过按右侧的按钮决定是否需要导航方向。
将此添加到您的应用程序的代码非常简单:
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 之旅中坚持使用该框架的人——尽管存在一些早期障碍。
你赢了我!我之前正要回答这个问题,但是当我重新加载页面时,我看到你已经回答了。虽然看起来您已经找到了问题的解决方案,但我还是想在这里发布我的答案。请看下面:
我找不到以编程方式显示地图工具栏的方法(用于导航到右下角给定位置的选项),因为您确实需要单击标记才能显示它。但这是我认为适合您的用例的解决方法:
- 通过在
GoogleMap()
小部件中设置 mapToolbarEnabled: false
来禁用地图工具栏。 (无论如何,地图工具栏仅适用于 Android)
- 创建自定义地图工具栏,从应用程序启动 Google Maps and Directions URL。该工具栏仅在您 select 列表视图中的位置或单击标记时显示。
我使用 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';
}
}
然后我在自定义地图工具栏小部件上使用了上述方法
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),
]),
);
}
我正在尝试开发一种用户体验,向用户提供前往的地点列表,并且在select访问其中一个地点后,我希望它
- 在地图上添加标记
- 显示信息window
- 提供导航至 位置。
我能够使用信息 from this PR(似乎没有官方文档)从这里开始:
为此:
但是,显示标记信息仍然不会使给定标记“激活”。当我 select 标记时,插件的功能实际上会显示用于导航到右下角给定位置的选项,如下所示:
我想要的是 select 列表底部的场地离子按一次自动显示第三张图片中的所有三个标准。即再次:
- 位置标记
- 信息window
- 导航到该位置的选项。
现在,用户必须单击底部列表中的条目,然后相当不直观地 单击地图上的标记 才能使用导航选项出现。
我将如何以编程方式启动当用户在 select 从列表中“点击”标记时发生的“点击”事件?
这是我当前用于更改视口、添加标记和显示信息的代码 window:
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));
});
}
现在,我的解决方案确实添加了标记并显示了信息 window,但很快就给用户提供了导航到该位置的选项 ,除非 用户单击标记。在目前的状态下,我构建了一些可以提供非常次优的用户体验的东西。
我已经尝试过 highlighting the marker 等替代解决方案,但它并不完全具备我正在寻找的功能。我不明白插件中发生了什么事件,“selects”标记点击,我发现所有尝试“以编程方式”select 标记做了一些版本的突出显示。简单地说明在单击标记时在哪里查看正在启动的事件会有所帮助。
我没有得出完整的答案,但我想分享我的经验,以防其他人遇到这个问题并感到困惑。通过浏览 Flutter Github / 在论坛中询问,我得到了三个关键要点:
据我所知,Flutter中没有办法模拟marker的“敲击”。我尝试查看 the Kotlin/Swift APIs for platform channels 来自己编写其中的一些功能,但老实说,它离我的驾驶室还很远,我为此浪费了很多时间。这也可能导致必须与 Google 的好人一起完成批准程序才能接受我的更改,但我个人现在还没有时间。
我发现了一个名为 Maps Launcher 的包,Craig 在评论部分也提到了它,它能够通过两种方法启动地图应用程序 - 通过查询启动和通过以下方式启动Latitude/Longitude。此功能实际上与点击标记然后点击右下角的两个地图选项之一 select 时获得的功能相同。
我发现两者的主要区别 点击标记时获得的图标是一个启动 方向查询,另一个方向经纬度 - 只是 比如 Maps Launcher 插件。
因此,根据这三个信息,我重新设计了应用程序:
看起来像这样:
现在是用户:
- 从列表中选择一个位置。
- 选择新位置会添加一个标记并显示该位置的信息窗口
- 可以点击右边的按钮导航到指定位置。
在我看来,这种体验要干净得多 - 在 select 标记时,您可以启动的两个地图选项(通过查询与 lat/long)之间没有歧义,因为启动地图图标的按钮现在位于列表视图上。这也使您可以很容易地导航到每个标记,只需在列表视图中单击它,然后通过按右侧的按钮决定是否需要导航方向。
将此添加到您的应用程序的代码非常简单:
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 之旅中坚持使用该框架的人——尽管存在一些早期障碍。
你赢了我!我之前正要回答这个问题,但是当我重新加载页面时,我看到你已经回答了。虽然看起来您已经找到了问题的解决方案,但我还是想在这里发布我的答案。请看下面:
我找不到以编程方式显示地图工具栏的方法(用于导航到右下角给定位置的选项),因为您确实需要单击标记才能显示它。但这是我认为适合您的用例的解决方法:
- 通过在
GoogleMap()
小部件中设置mapToolbarEnabled: false
来禁用地图工具栏。 (无论如何,地图工具栏仅适用于 Android) - 创建自定义地图工具栏,从应用程序启动 Google Maps and Directions URL。该工具栏仅在您 select 列表视图中的位置或单击标记时显示。
我使用 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';
}
}
然后我在自定义地图工具栏小部件上使用了上述方法
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),
]),
);
}