根据 Flutter 中的变量更新自定义标记的图标
Update custom marker's icons depending on a variable in Flutter
我完全是一个 flutter 菜鸟,我正在尝试创建一个应用程序,在地图上向我显示一些指向某些传感器位置的标记。标记的图标将根据为每个传感器收集的数据而有所不同。
到目前为止我已经做到了:
- 在用户位置显示地图
- 为所有传感器放置标记
- 将标记图标更改为自定义图标
- 添加对话框,包含
每个标记的传感器数据
我需要的:
- 根据传感器的数据对标记使用不同的图标
这是我在地图上显示标记的方式:
@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应用程序生命周期的理解有问题,希望你能帮助我。
对不起,我不能使用评论。
如果在 setState 中添加登录会怎样?
我通过在 initState 方法中设置所有自定义引脚来解决这个问题,因为将图像转换为字节是一个异步过程,而且由于我设置标记的动态选择的方式,它没有'没有足够的时间进行转换。
所以我所做的是设置一个方法,将每个图像转换为 initState 中的字节,将这些值传递给全局变量,然后在每种情况下有条件地使用它们。
我完全是一个 flutter 菜鸟,我正在尝试创建一个应用程序,在地图上向我显示一些指向某些传感器位置的标记。标记的图标将根据为每个传感器收集的数据而有所不同。
到目前为止我已经做到了:
- 在用户位置显示地图
- 为所有传感器放置标记
- 将标记图标更改为自定义图标
- 添加对话框,包含 每个标记的传感器数据
我需要的:
- 根据传感器的数据对标记使用不同的图标
这是我在地图上显示标记的方式:
@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应用程序生命周期的理解有问题,希望你能帮助我。
对不起,我不能使用评论。
如果在 setState 中添加登录会怎样?
我通过在 initState 方法中设置所有自定义引脚来解决这个问题,因为将图像转换为字节是一个异步过程,而且由于我设置标记的动态选择的方式,它没有'没有足够的时间进行转换。 所以我所做的是设置一个方法,将每个图像转换为 initState 中的字节,将这些值传递给全局变量,然后在每种情况下有条件地使用它们。