根据 Flutter 中的变量更新自定义标记的图标

Posted

技术标签:

【中文标题】根据 Flutter 中的变量更新自定义标记的图标【英文标题】:Update custom marker's icons depending on a variable in Flutter 【发布时间】:2020-05-01 09:34:59 【问题描述】:

我完全是个菜鸟,我正在尝试创建一个应用程序,在地图上显示一些标记,指向一些传感器的位置。根据为每个传感器收集的数据,标记的图标会有所不同。

到目前为止,我已经做到了:

在用户位置上显示地图 为所有传感器放置标记 将标记图标更改为自定义图标 添加对话框,包含 每个标记的传感器数据

我需要什么:

根据传感器数据使用不同的标记图标

这就是我在地图上显示标记的方式:

@override
     Widget build(BuildContext context)     
       
      var userLocation = Provider.of<UserLocation>(context );
      
      Set<Marker> markers = Set();           
   
   
   //this cycle creates markers with sensor's data
      for(var i=0;   i < sensors.length ; i++)
       var tempF=(strSensors[i]["temp_f"]).toString();
       double pm2_5= double.parse(strSensors[i]["PM2_5Value"]);     
       
       //It returns a tuple wit Aqi value(item1) and description(item2). Depending on item1 value the marker's icon should change.  
       var Aqi=AqiCalculation().AqiValue(pm2_5);


      //my attempt to update the value of the asset's path depending on Aqi.item1 value 
       setState(()
         marcador=updateCustomMapPin(Aqi.item1); 
       );       
       
   
        Marker resultMarker = Marker(
     
        markerId: MarkerId(strSensors[i]["ID"].toString()),     
        position: LatLng(strSensors[i]["Lat"].toDouble(),strSensors[i]["Lon"].toDouble()),
        icon: BitmapDescriptor.fromBytes(markerIcon),
        onTap: ()  

          //shows an image in dialog box depending on Aqi value
                   if(Aqi.item1 > 80)
                     image="https://i.gifer.com/72fB.gif";               
                   
                   else
                     image= "https://raw.githubusercontent.com/Shashank02051997/FancyGifDialog-android/master/GIF's/gif14.gif";
                                                       
                  
   
        String tempC;
                   tempC=((int.parse(tempF)-32)/1.8).toStringAsPrecision(4);                   
   
                                showDialog<void>(                                   
                       context: context,
                       builder: (_) => NetworkGiffyDialog(
                               key: keys[1],                            
                               image: Image.network(
                                 image,
                                 fit: BoxFit.cover,                              
                                // alignment:Alignment.bottomLeft,
                               ),
                               entryAnimation: EntryAnimation.TOP_LEFT,
                               title: Text('Sensor: $strSensors[i]["Label"]'
                               ,
                                 textAlign: TextAlign.center,
                                 style: TextStyle(
                                     fontSize: 22.0, fontWeight: FontWeight.bold),
                               ),
                               description: Text(
                                 'PM2.5: $pm2_5 Temp:$tempC° Aqi:$Aqi.item1 Status:$Aqi.item2',
                                 textAlign: TextAlign.center,
                                 style: TextStyle(
                                     fontSize: 22.0, fontWeight: FontWeight.normal),
                                  
                               ),
                               
                               onlyOkButton: true,
                               onOkButtonPressed: ()
                                 Navigator.pop(context);//closes dialogbox
                               ,                                   
                             )
                    );          
             
        
       );
   // Add it to Set
       markers.add(resultMarker);
         

要更改默认标记图标,我这样做了:

  @override
     void initState()
       super.initState();
       setCustomMappin('android/assets/Cloudgray.png');
        
    
    //Converts image to Unint8List
         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();
    

   
     
     void setCustomMappin(marker)async 

       markerIcon = await getBytesFromAsset(marker, 150);
     

这会将所有图标更改为我的默认图标资产。我试图通过在创建所有标记的循环上传递它来动态更新资产的路径:

setState(()
             marcador=updateCustomMapPin(Aqi.item1); 
           ); 

使用这个功能的:

    //returns icon path depending on the value
     updateCustomMapPin(value)  
    
      String marker='';
    
           if(value<=50)
            marker = 'android/assets/Cloudgreen.png';
           
           else if(value>50  && value<=100)
             marker='android/assets/Cloudyellow.png';
           
           else if(value>100  && value<=150)
             marker='android/assets/CloudOrange.png';
           
           else if(value>150  && value<=200)
             marker='android/assets/Cloudred.png';
          

 
       else if(value>200  && value<=300)
         marker='android/assets/Cloudpurple.png';
       
       else
       marker='android/assets/Cloudtoxic.png';
       

       return marker;
      
     

这就是我卡住的地方,尽管如此,标记的图标并没有改变,在创建每个标记的那一刻,都会指示正确的图标。

可能是我对 Flutter 应用的生命周期理解的问题,希望你能帮助我。

【问题讨论】:

【参考方案1】:

对不起,我不能使用评论。

如果在 setState 中添加 log 会发生什么?

【讨论】:

你的意思是这样吗?: setState(() marcador=updateCustomMapPin(Aqi.item1); log(marcador); );输出: [log] android/assets/CloudOrange.png [log] android/assets/CloudOrange.png [log] android/assets/CloudOrange.png [log] android/assets/Cloudyellow.png [log] android/assets/CloudOrange .png [日志] android/assets/Cloudyellow.png [日志] android/assets/CloudOrange.png [日志] android/assets/CloudOrange.png [日志] android/assets/Cloudyellow.png [日志] android/assets/CloudOrange .png【参考方案2】:

我通过在 initState 方法中设置所有自定义引脚来解决这个问题,出现问题是因为图像到字节的转换是一个异步过程,并且由于我设置标记的动态选择的方式它没有有足够的时间进行转换。 所以我所做的是设置一个方法,将每个图像转换为 initState 中的字节,将这些值传递给全局变量,然后在每种情况下在条件下使用它们。

【讨论】:

以上是关于根据 Flutter 中的变量更新自定义标记的图标的主要内容,如果未能解决你的问题,请参考以下文章

google_maps_flutter - 自定义标记图标:无法启用 MyLocation 图层,因为未授予位置权限

Flutter 多自定义图标未显示在地图视图上

带有矢量资产图标的 android 谷歌地图中的自定义标记

Flutter - 使用 StreamBuilder 提供对谷歌地图的实时更新

如何在 Flutter 中自定义谷歌地图标记图标

Flutter:如何将多张照片或图标内的一张照片链接到地理位置标记?