Je colle le code pertinent ci-dessous, mais vous pourrez peut-être y répondre en fonction de ma pseudo-explication.
Je suis à l'aide d'un futurbuilder pour créer une liste de réception.
Future<List<Location>> _listFuture
variable (qui est l'avenir pour le futurbuilder).Le problème est que le listview/Contre -erer/Listtile est conduit par un
Future<List<Location>>
. Je peux transmettre l'index "taraudé" à mon gestionnaire ONTAP, mais je ne crois pas que je puisse avoir mon _Changebackground () juste mettre à jour la valeur de l'arrière-plan pour l'index sélectionné et la création d'appels (), car vous ne pouvez pas accéder à/mettre à jour directement un avenir comme ça ( Je reçois l'erreur ERROR: The operator '[]' isn't defined for the class 'Future<List<Location>>'.
)
Je ne suis pas sûr que je prends la bonne approche. Dans ce cas, je suppose que je pouvais toujours séparer théoriquement le suivi des couleurs "fond" dans une nouvelle liste séparée (en dehors du futur) et suivre/référencer-la de cette manière en utilisant des index alignés de l'ONTAP ().
Cependant, je ne suis pas sûr que cela fonctionnerait toujours. À l'avenir, je pourrais avoir besoin de changer les valeurs/l'état de ce qui a été retourné à l'avenir. Par exemple, pensez à si je voulais pouvoir cliquer sur un élément de la liste et mettre à jour le "Nom d'entreprise". Dans ce cas, je modifierais une valeur stockée dans le futur directement. Je suppose que je pourrais techniquement envoyer le nouveau nom au serveur et rafraîchir complètement la liste de cette façon, mais cela semble inefficace (que s'ils décident de "annuler" et non d'enregistrer les modifications?).
Toute aide est appréciée. Merci!
cette classe détient en fait les données pertinentes de la liste
// Location
class Location {
// members
String locationID;
String locationName;
String companyName;
String backgroundColor = 'fc7303';
// constructor?
Location({this.locationID, this.locationName, this.companyName});
// factory?
factory Location.fromJson(Map<String, dynamic> json) {
return Location(
locationID: json['locationID'],
locationName: json['locationName'],
companyName: json['companyName'],
);
}
}
cette classe est la réponse parent JSON qui a des messages "Résultats" (Success/Error). Il instancite de la classe ci-dessus en tant que liste de suivre les enregistrements d'entreprise/emplacement réels
//jsonResponse
class jsonResponse{
String result;
String resultMsg;
List<Location> locations;
jsonResponse({this.result, this.resultMsg, this.locations});
factory jsonResponse.fromJson(Map<String, dynamic> parsedJson){
var list = parsedJson['resultSet'] as List;
List<Location> locationList = list.map((i) => Location.fromJson(i)).toList();
return jsonResponse(
result: parsedJson['result'],
resultMsg: parsedJson['resultMsg'],
locations: locationList
);
}
} // jsonResponse
voici les widgets d'état et d'états qui utilisent les classes ci-dessus pour analyser les données API et créer ListView
class locationsApiState extends State<locationsApiWidget> {
// list to track AJAX results
Future<List<Location>> _listFuture;
// init - set initial values
@override
void initState() {
super.initState();
// initial load
_listFuture = updateAndGetList();
}
Future<List<Location>> updateAndGetList() async {
var response = await http.get("http://XXX.XXX.XXX.XXX/api/listCompanies.php");
if (response.statusCode == 200) {
var r1 = json.decode(response.body);
jsonResponse r = new jsonResponse.fromJson(r1);
return r.locations;
} else {
throw Exception('Failed to load internet');
}
}
_changeBackground(int index){
print("in changebackground(): ${index}"); // this works!
_listFuture[index].backgroundColor = '34bdeb'; // ERROR: The operator '[]' isn't defined for the class 'Future<List<Location>>'.
}
// build() method
@override
Widget build(BuildContext context) {
return new FutureBuilder<List<Location>>(
future: _listFuture,
builder: (context, snapshot){
if (snapshot.connectionState == ConnectionState.waiting) {
return new Center(
child: new CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return new Text('Error: ${snapshot.error}');
} else {
final items = snapshot.data;
return new Scrollbar(
child: new RefreshIndicator(
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
//Even if zero elements to update scroll
itemCount: items.length,
itemBuilder: (context, index) {
return
Container(
color: HexColor(items[index].backgroundColor),
child:
ListTile(
title: Text(items[index].companyName),
onTap: () {
print("Item at $index is ${items[index].companyName}");
_changeBackground(index);
} // onTap
)
);
},
),
onRefresh: () {
// implement later
return;
} // refreshList,
),
);
}// else
} // builder
); // FutureBuilder
} // build
} // locationsApiState class
class locationsApiWidget extends StatefulWidget {
@override
locationsApiState createState() => locationsApiState();
}
classe d'assistance (prise de quelque part sur Stackoverflow) pour convertir HEX en des couleurs entière
class HexColor extends Color {
static int _getColorFromHex(String hexColor) {
hexColor = hexColor.toUpperCase().replaceAll("#", "");
if (hexColor.length == 6) {
hexColor = "FF" + hexColor;
}
return int.parse(hexColor, radix: 16);
}
HexColor(final String hexColor) : super(_getColorFromHex(hexColor));
}
Merci!
Ce que je recommanderais, c'est supprimer la couleur de fond de votre classe d'emplacement et que vous stockez plutôt dans votre état que les emplacements sont sélectionnés. De cette façon, votre liste de localisation n'a pas besoin de changer lorsque des éléments sont sélectionnés. Je créerais également un apatridementWidget pour votre élément de localisation, qui définirait la couleur d'arrière-plan, selon qu'elle soit sélectionnée ou non. Alors:
// for the LocationItem widget callback
typedef void tapLocation(int index);
class locationsApiState extends State<locationsApiWidget> {
// list to track AJAX results
Future<List<Location>> _listFuture;
final var selectedLocationIndices = Set<int>();
// init - set initial values
@override
void initState() {
super.initState();
// initial load
_listFuture = updateAndGetList();
}
Future<List<Location>> updateAndGetList() async {
var response = await http.get("http://XXX.XXX.XXX.XXX/api/listCompanies.php");
if (response.statusCode == 200) {
var r1 = json.decode(response.body);
jsonResponse r = new jsonResponse.fromJson(r1);
return r.locations;
} else {
throw Exception('Failed to load internet');
}
}
void _toggleLocation(int index) {
if (selectedLocationIndices.contains(index))
selectedLocationIndices.remove(index);
else
selectedLocationIndices.add(index);
}
// build() method
@override
Widget build(BuildContext context) {
return new FutureBuilder<List<Location>>(
future: _listFuture,
builder: (context, snapshot){
if (snapshot.connectionState == ConnectionState.waiting) {
return new Center(
child: new CircularProgressIndicator(),
);
} else if (snapshot.hasError) {
return new Text('Error: ${snapshot.error}');
} else {
final items = snapshot.data;
return new Scrollbar(
child: new RefreshIndicator(
child: ListView.builder(
physics: const AlwaysScrollableScrollPhysics(),
//Even if zero elements to update scroll
itemCount: items.length,
itemBuilder: (context, index) {
return LocationItem(
isSelected: selectedLocationIndices.contains(index),
onTap: () => setState({
_toggleLocation(index);
})
);
},
),
onRefresh: () {
// implement later
return;
} // refreshList,
),
);
}// else
} // builder
); // FutureBuilder
} // build
} // locationsApiState class
class locationsApiWidget extends StatefulWidget {
@override
locationsApiState createState() => locationsApiState();
}
Et la liste de liste d'articles:
class LocationItem extends StatelessWidget {
final bool isSelected;
final Function tapLocation;
const LocationItem({@required this.isSelected, @required this.tapLocation, Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: isSelected ? HexColor('34bdeb') : HexColor('fc7303'),
child: ListTile(
title: Text(items[index].companyName),
onTap: () => tapLocation() // onTap
)
);
}
}
Pardonne-moi, je ne peux pas compiler donc j'espère que c'est correct. Mais je pense que vous obtenez l'idée: Demandez au widget sotculier de garder une trace des emplacements sélectionnés séparément et laissez l'emplacement décider de la manière de se rendre quand elle est reconstruite.