英文:
How to set a custom image as icon for gmap marker in flutter?
问题
我想在我制作的Flutter GMap上添加一些标记。我尝试了这段代码,但它不起作用。我已经在pubspec中添加了链接,图片也在assets中。
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() async {
_markers.clear();
_markers.add(Marker(
markerId:
MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
地图上没有添加标记,但在调试控制台中显示以下错误:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] 未处理的异常:
setState()回调参数返回了一个Future。E/flutter ( 7655): _HomePageState#3d9e4上的setState()方法使用返回Future的闭包或方法进行了调用。可能标记为"async"。E/flutter ( 7655): 请不要在调用setState()时执行异步工作,首先执行工作(不更新小部件状态),然后在调用setState()时同步更新状态。E/flutter ( 7655): #0 State.setState.<匿名闭包> package:flutter/.../widgets/framework.dart:1112 E/flutter ( 7655): #1 State.setState package:flutter/.../widgets/framework.dart:1128 E/flutter ( 7655): #2 _HomePageState.addMarker package:mymapp/screens/home_page.dart:417 E/flutter ( 7655): <异步悬挂> E/flutter ( 7655): E/MethodChannel#plugins.flutter.dev/google_maps_android_0( 7655): 未能处理方法调用
这个错误是因为setState
方法不能接受返回Future
的异步函数作为参数。您应该先执行异步操作,然后再在setState
内同步更新状态。如果需要异步加载标记,请将加载标记的代码移出setState
,然后在加载完成后再更新标记状态。
英文:
I wanted to add some markers in a gmap on flutter I made. I tried this code but it doesn't work. I have added link in pubspec and picture is in assets too.
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() async {
_markers.clear();
_markers.add(Marker(
markerId:
MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
no marker gets addded on the map but shows this error in debug console
> [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception:
> setState() callback argument returned a Future. E/flutter ( 7655): The
> setState() method on _HomePageState#3d9e4 was called with a closure or
> method that returned a Future. Maybe it is marked as "async".
> E/flutter ( 7655): Instead of performing asynchronous work inside a
> call to setState(), first execute the work (without updating the
> widget state), and then synchronously update the state inside a call
> to setState(). E/flutter ( 7655): #0 State.setState.<anonymous
> closure> package:flutter/…/widgets/framework.dart:1112 E/flutter (
> 7655): #1 State.setState
> package:flutter/…/widgets/framework.dart:1128 E/flutter ( 7655): #2
> _HomePageState.addMarker package:mymapp/screens/home_page.dart:417 E/flutter ( 7655): <asynchronous suspension> E/flutter ( 7655):
> E/MethodChannel#plugins.flutter.dev/google_maps_android_0( 7655):
> Failed to handle method call
答案1
得分: 0
你应该在initState
中执行这个操作。
final _controller = Completer<GoogleMapController>();
var _markers = const <Marker>{};
Set<Marker> get markers => _markers;
set markers(Set<Marker> val) {
setState(() => _markers = val);
}
...
@override
void initState() {
initializeMap();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
...
markers: markers,
...
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
);
}
...
void initializeMap(){
markers = {
Marker(
markerId: MarkerId(UniqueKey().toString()),
icon: await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(),
'assets/images/icons/pin.png',
),
position: target.target,
rotation: target.tilt,
)
};
}
英文:
You should do this in initState
final _controller = Completer<GoogleMapController>();
var _markers = const <Marker>{};
Set<Marker> get markers => _markers;
set markers(Set<Marker> val) {
setState(() => _markers = val);
}
...
@override
void initState() {
initializeMap();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
...
markers: markers,
...
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
);
}
...
void initializeMap(){
markers = {
Marker(
markerId: MarkerId(UniqueKey().toString()),
icon: await BitmapDescriptor.fromAssetImage(
const ImageConfiguration(),
'assets/images/icons/pin.png',
),
position: target.target,
rotation: target.tilt,
)
};
}
答案2
得分: 0
你遇到这个错误是因为你试图在setState的块中使用"Async"。
你可以移除async并修改你的代码如下:
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() {
_markers.clear();
_markers.add(Marker(
markerId: MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
英文:
you have this error because you are trying to use "Async" in the block of a setState.
you can remove the async and modify your code to this:
Future<void> addMarker(
LatLng mLatLng, String mTitle, String mDescription) async {
BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
ImageConfiguration(),
"assets/images/icons/pin.png",
);
setState(() *** ----- delete the async here {
_markers.clear();
_markers.add(Marker(
markerId:
MarkerId((mTitle + "_" + _markers.length.toString()).toString()),
position: mLatLng,
infoWindow: InfoWindow(
title: mTitle,
snippet: mDescription,
),
icon: markerbitmap //BitmapDescriptor.defaultMarker,
));
});
}
答案3
得分: 0
首先,创建一个处理资源路径并接收大小的方法(大小可以是宽度、高度或两者之一,但只使用一个将保持纵横比)。
import 'dart:ui' as ui;
Future<Uint8List> getBytesFromAsset(String path, int width) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
ui.FrameInfo fi = await codec.getNextFrame();
return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
}
然后,只需将其添加到地图上并使用正确的描述符:
final Uint8List markerIcon = await getBytesFromAsset('assets/images/flutter.png', 100);
final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));
参考链接:https://stackoverflow.com/questions/53633404/how-to-change-the-icon-size-of-google-maps-marker-in-flutter
英文:
I DID THIS.
First, create a method that handles the asset path and receives a size (this can be either the width, height, or both, but using only one will preserve ratio).
import 'dart:ui' as ui;
Future<Uint8List> getBytesFromAsset(String path, int width) async {
ByteData data = await rootBundle.load(path);
ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
ui.FrameInfo fi = await codec.getNextFrame();
return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
}
Then, just add it to your map using the right descriptor:
final Uint8List markerIcon = await getBytesFromAsset('assets/images/flutter.png', 100);
final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论