有没有办法使用官方的Flutter Google Maps插件在地图上显示自定义标记?根据文档找不到任何方法。
BitmapDescriptor customIcon;
// make sure to initialize before map loading
BitmapDescriptor.fromAssetImage(ImageConfiguration(size: Size(12, 12)),
'assets/images/car-icon.png')
.then((d) {
customIcon = d;
});
final nearbyCarsLocation = [
LatLng(24.9286825, 67.0403249),
LatLng(24.985577, 67.0661056), //24.9294892,67.0391903,18.73z
];
void _getNearByCars() {
for (var i = 0; i < nearbyCarsLocation.length; i++) {
var now = new DateTime.now().millisecondsSinceEpoch;
_markers.add(Marker(
markerId: MarkerId(nearbyCarsLocation[i].toString() + now.toString()),
position: nearbyCarsLocation[i],
// infoWindow: InfoWindow(title: address, snippet: "go here"),
icon: customIcon ));
}
notifyListeners();
}
希望这将有助于获得附近的定制地点
我正在使用:
controller.addMarker(MarkerOptions(
icon: BitmapDescriptor.fromAsset("images/restaurant.png"),
position: LatLng(40.017870, -105.278350),
));
它在 Android 上运行良好,但在 iOS 上不起作用。
BitmapDescriptor.fromAsset
已弃用
请使用
BitmapDescriptor.fromAssetImage
代替。
在选择适当的资源时,它会考虑设备 DPI。请参阅声明分辨率感知的图像资源。
算法阿西 https://www.youtube.com/watch?v=ajuo0HjN3lY&t=905s
BitmapDescriptor icon;
@override
void initState() {
getIcons();
super.initState();
}
// Cargar imagen del Marker
getIcons() async {
var icon = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(devicePixelRatio: 3.2),
"assets/images/markeruser.png");
setState(() {
this.icon = icon;
});
}
// Crear Marker
createMarkers() {
markers.add(
Marker(
markerId: MarkerId("MarkerCurrent"),
position: currentLocation,
icon: icon,
infoWindow: InfoWindow(
title: "Mi Ubicacion",
snippet:
"Lat ${currentLocation.latitude} - Lng ${currentLocation.longitude}"),
draggable: true,
onDragEnd: onDragEnd,
),
);
}
您可以将 Flutter 小部件用于此类的自定义标记
import 'package:flutter/material.dart';
import 'dart:typed_data';
import 'package:flutter/rendering.dart';
import 'dart:ui' as ui;
/// This just adds overlay and builds [_MarkerHelper] on that overlay.
/// [_MarkerHelper] does all the heavy work of creating and getting bitmaps
class MarkerGenerator {
final Function(List<Uint8List>) callback;
final List<Widget> markerWidgets;
MarkerGenerator(this.markerWidgets, this.callback);
void generate(BuildContext context) {
WidgetsBinding.instance
.addPostFrameCallback((_) => afterFirstLayout(context));
}
void afterFirstLayout(BuildContext context) {
addOverlay(context);
}
void addOverlay(BuildContext context) {
OverlayState overlayState = Overlay.of(context);
OverlayEntry entry;
entry = OverlayEntry(
builder: (context) {
return _MarkerHelper(
markerWidgets: markerWidgets,
callback: (List<Uint8List> bitmapList) {
// Given callback function
callback.call(bitmapList);
// Remove marker widget stack from Overlay when finished
entry.remove();
},
);
},
maintainState: true);
overlayState.insert(entry);
}
}
/// Maps are embeding GoogleMap library for Andorid/iOS into flutter.
///
/// These native libraries accept BitmapDescriptor for marker, which means that for custom markers
/// you need to draw view to bitmap and then send that to BitmapDescriptor.
///
/// Because of that Flutter also cannot accept Widget for marker, but you need draw it to bitmap and
/// that's what this widget does:
///
/// 1) It draws marker widget to tree
/// 2) After painted access the repaint boundary with global key and converts it to uInt8List
/// 3) Returns set of Uint8List (bitmaps) through callback
class _MarkerHelper extends StatefulWidget {
final List<Widget> markerWidgets;
final Function(List<Uint8List>) callback;
const _MarkerHelper({Key key, this.markerWidgets, this.callback})
: super(key: key);
@override
_MarkerHelperState createState() => _MarkerHelperState();
}
class _MarkerHelperState extends State<_MarkerHelper> with AfterLayoutMixin {
List<GlobalKey> globalKeys = [];
@override
void afterFirstLayout(BuildContext context) {
_getBitmaps(context).then((list) {
widget.callback(list);
});
}
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset(MediaQuery.of(context).size.width, 0),
child: Material(
type: MaterialType.transparency,
child: Stack(
children: widget.markerWidgets.map((i) {
final markerKey = GlobalKey();
globalKeys.add(markerKey);
return RepaintBoundary(
key: markerKey,
child: i,
);
}).toList(),
),
),
);
}
Future<List<Uint8List>> _getBitmaps(BuildContext context) async {
var futures = globalKeys.map((key) => _getUint8List(key));
return Future.wait(futures);
}
Future<Uint8List> _getUint8List(GlobalKey markerKey) async {
RenderRepaintBoundary boundary =
markerKey.currentContext.findRenderObject();
var image = await boundary.toImage(pixelRatio: 2.0);
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
return byteData.buffer.asUint8List();
}
}
/// AfterLayoutMixin
mixin AfterLayoutMixin<T extends StatefulWidget> on State<T> {
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => afterFirstLayout(context));
}
void afterFirstLayout(BuildContext context);
}
使用示例
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:map_marker_sample/gist/Gist.dart';
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
List<Marker> markers = [];
@override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(45.811328, 15.975862), zoom: 8),
markers: markers.toSet(),
),
],
),
);
}
@override
void initState() {
super.initState();
MarkerGenerator(markerWidgets(), (bitmaps) {
setState(() {
markers = mapBitmapsToMarkers(bitmaps);
});
}).generate(context);
}
List<Marker> mapBitmapsToMarkers(List<Uint8List> bitmaps) {
List<Marker> markersList = [];
bitmaps.asMap().forEach((i, bmp) {
final city = cities[i];
markersList.add(Marker(
markerId: MarkerId(city.name),
position: city.position,
icon: BitmapDescriptor.fromBytes(bmp)));
});
return markersList;
}
}
// Example of marker widget
Widget _getMarkerWidget(String name) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 3, vertical: 1.5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.black, width: 1),
color: Colors.white,
shape: BoxShape.rectangle,
),
child: Text(
name,
style: TextStyle(fontSize: 14, color: Colors.black),
),
),
);
}
// Example of backing data
List<City> cities = [
City("Zagreb", LatLng(45.792565, 15.995832)),
City("Ljubljana", LatLng(46.037839, 14.513336)),
City("Novo Mesto", LatLng(45.806132, 15.160768)),
City("Varaždin", LatLng(46.302111, 16.338036)),
City("Maribor", LatLng(46.546417, 15.642292)),
City("Rijeka", LatLng(45.324289, 14.444480)),
City("Karlovac", LatLng(45.489728, 15.551561)),
City("Klagenfurt", LatLng(46.624124, 14.307974)),
City("Graz", LatLng(47.060426, 15.442028)),
City("Celje", LatLng(46.236738, 15.270346))
];
List<Widget> markerWidgets() {
return cities.map((c) => _getMarkerWidget(c.name)).toList();
}
class City {
final String name;
final LatLng position;
City(this.name, this.position);
}
来源链接:https://infinum.com/the-capsized-eight/creating-custom-markers-on-google-maps-in-flutter-apps
github存储库:https://github.com/itsJoKr/markers_generator_sample
根据新插件 BitmapDescriptor.fromAsset("images/restaurant.png") 无法正常工作,因此请参考此 link 并找到我的解决方案。
Future<BitmapDescriptor> _getAssetIcon(BuildContext context) async {
final Completer<BitmapDescriptor> bitmapIcon =
Completer<BitmapDescriptor>();
final ImageConfiguration config = createLocalImageConfiguration(context);
const AssetImage('assets/red_square.png')
.resolve(config)
.addListener((ImageInfo image, bool sync) async {
final ByteData bytes =
await image.image.toByteData(format: ImageByteFormat.png);
final BitmapDescriptor bitmap =
BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
bitmapIcon.complete(bitmap);
});
return await bitmapIcon.future;}
然后像这样使用它
void _add(LatLng position,String address) async{
final MarkerId markerId = MarkerId('1');
BitmapDescriptor markericon = await _getAssetIcon(context);
// creating a new MARKER
final Marker marker = Marker(
markerId: markerId,
position: position,
infoWindow: InfoWindow(title: address, snippet: 'go here'),
icon: markericon
);
setState(() {
_markers[markerId] = marker;
});}
希望它对你有用。
**试试这个,
_createMarkerImageFromAsset("assets/locationMarker.png");
Future <BitmapDescriptor> _createMarkerImageFromAsset(String iconPath) async {
ImageConfiguration configuration = ImageConfiguration();
bitmapImage = await BitmapDescriptor.fromAssetImage(
configuration,iconPath);
return bitmapImage;
}
将位图图像设置为标记
Marker(
markerId: MarkerId('value'),
icon: bitmapImage,
position: LatLng(),
);
final bitmapIcon = await BitmapDescriptor.fromAssetImage(ImageConfiguration(size: Size(48,48)), 'assets/images/marker.png');
Marker(
markerId: MarkerId('marker_2'),
position: LatLng(_position.target.latitude, _position.target.longitude),
draggable: true,
icon: bitmapIcon,
)
尝试上面的代码,使用异步编程。
实际上只有 google_maps 的示例存储库的注释代码才有效...因为 flutter sdk 在 API 中有一些更改(我目前在 1.8 中) 所以,这就是函数,与 kapil 在 API 中进行一些更改的答案相同,您只需要更改图像路由的“assets/red_square.png”行即可。
Future<BitmapDescriptor> _getAssetIcon(BuildContext context) async {
final Completer<BitmapDescriptor> bitmapIcon =
Completer<BitmapDescriptor>();
final ImageConfiguration config = createLocalImageConfiguration(context);
const AssetImage('assets/red_square.png')
.resolve(config)
.addListener(ImageStreamListener((ImageInfo image, bool sync) async {
final ByteData bytes =
await image.image.toByteData(format: ImageByteFormat.png);
final BitmapDescriptor bitmap =
BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
bitmapIcon.complete(bitmap);
}));
return await bitmapIcon.future;
}
可能如果你创建一个 BitMapDescriptor 变量,你只需要在添加标记之前第一次调用这个函数,但不要忘记“等待”。
还建议将另外 2 个较大尺寸的图像放入名称为(2.0x 和 3.0x)的文件夹中,您可以在
示例图像中看到分辨率 不要忘记在 pubspec.yaml 中取消注释“/assets”
首先,创建一个变量,
late BitmapDescriptor customIcon;
然后创建一个方法
customMarkers
并添加以下代码。
void customMarker() {
BitmapDescriptor.fromAssetImage(ImageConfiguration(),'assets/images/filled_circle.png').
then((value) => {
customIcon = value
});
}
之后在初始化状态中调用
customMarker
方法,以便在创建地图之前加载您的图像。
@override
void initState() {
// your code here
customMarker();
}
现在,当应用程序启动时,图像将存储在您的变量中,并在您的
Marker
icon
参数中使用该变量,如下所示:Marker(
icon : customIcon,)
MarkerOptions(
position: LatLng(41.4219999, 63.0862462),
infoWindowText: InfoWindowText("Yur Title", "Your Content"),
icon: BitmapDescriptor.fromAsset('images/your_image.png',),
),
BitmapDescriptor.fromBytes
import 'package:flutter/services.dart';
final asset = await rootBundle.load('assets/images/marker.png');
final icon = BitmapDescriptor.fromBytes(asset.buffer.asUint8List());
markers.add(
Marker(
markerId: MarkerId('id'),
icon: icon,
position: LatLng(lat, lng),
),
);
if (mounted) {
setState(() {});
}