如何在Flutter中将自定义图片设置为GMap标记的图标?

huangapple go评论59阅读模式
英文:

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&lt;void&gt; addMarker(
      LatLng mLatLng, String mTitle, String mDescription) async {
    BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
      ImageConfiguration(),
      &quot;assets/images/icons/pin.png&quot;,
    );
    setState(() async {
      _markers.clear();

      _markers.add(Marker(
          markerId:
              MarkerId((mTitle + &quot;_&quot; + _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&lt;GoogleMapController&gt;();

 var _markers = const &lt;Marker&gt;{};
  Set&lt;Marker&gt; get markers =&gt; _markers;
  set markers(Set&lt;Marker&gt; val) {
    setState(() =&gt; _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(),
         &#39;assets/images/icons/pin.png&#39;,
       ),
       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&lt;void&gt; addMarker(
      LatLng mLatLng, String mTitle, String mDescription) async {
    BitmapDescriptor markerbitmap = await BitmapDescriptor.fromAssetImage(
      ImageConfiguration(),
      &quot;assets/images/icons/pin.png&quot;,
    );
    setState(() *** ----- delete the async here {
      _markers.clear();

      _markers.add(Marker(
          markerId:
              MarkerId((mTitle + &quot;_&quot; + _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 &#39;dart:ui&#39; as ui;

Future&lt;Uint8List&gt; 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(&#39;assets/images/flutter.png&#39;, 100);
    final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));

REF: https://stackoverflow.com/questions/53633404/how-to-change-the-icon-size-of-google-maps-marker-in-flutter

huangapple
  • 本文由 发表于 2023年2月14日 20:51:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75448108.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定