155 votes

Comment mettre en place une liste déroulante dans Flutter ?

J'ai une liste de lieux que je veux implémenter comme une liste déroulante dans Flutter. Je suis assez novice dans ce langage. Voici ce que j'ai fait.

new DropdownButton(
  value: _selectedLocation,
  onChanged: (String newValue) {
    setState(() {
      _selectedLocation = newValue;
     });
},
items: _locations.map((String location) {
  return new DropdownMenuItem<String>(
     child: new Text(location),
  );
}).toList(),

Voici ma liste d'articles :

List<String> _locations = ['A', 'B', 'C', 'D'];

Et j'obtiens l'erreur suivante.

Another exception was thrown: 'package:flutter/src/material/dropdown.dart': Failed assertion: line 468 pos 15: 'value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not true.

Je suppose que la valeur de _selectedLocation devient nulle. Mais je l'ai initialisé comme ça.

String _selectedLocation = 'Please choose a location';

1 votes

Le problème est que la chaîne _selectedLocation = 'Please choose a location' ; ne figure pas dans les valeurs du DropdownMenuItem. Ce que vous essayez de faire est probablement un indice.

0 votes

295voto

Pravin Raj Points 557

Essayez ceci

new DropdownButton<String>(
  items: <String>['A', 'B', 'C', 'D'].map((String value) {
    return new DropdownMenuItem<String>(
      value: value,
      child: new Text(value),
    );
  }).toList(),
  onChanged: (_) {},
)

0 votes

J'ai essayé d'ajouter value : value sur DropdownMenuItem . Je reçois toujours la même erreur. Je suppose qu'il y a une erreur avec value : _selectedLocation dans le DropDownButton.

1 votes

Un grand merci à @Pravin Raj. Vous m'avez incité à réfléchir au type de liste renvoyée en forçant l'utilisation de la fonction DropdownMenuItem<String>

0 votes

La largeur des DropDowns dépasse la largeur de l'écran lorsque le texte de l'élément est très grand Eg :['sdfdfsd fas dgshdfgasduf vasydf asyda sd f asdf s df sdgf sd fsdg fhs gdfhds', 'fhsfsdhfjs dfsdkf sdf ssdf sdfs dfhjs dhfb fd ']. Aidez-moi @Pravin

101voto

cegas Points 777

Pour connaître la solution, allez à la fin de la réponse.

Tout d'abord, examinons ce que dit l'erreur (j'ai cité l'erreur qui se produit avec Flutter 1.2, mais l'idée est la même) :

Échec de l'assertion : ligne 560 pos 15 : 'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem item) => item.value == value).length == 1' : n'est pas vrai.

Il y a quatre or conditions. Au moins une d'entre elles doit être remplie :

  • Éléments (une liste de DropdownMenuItem widgets) ont été fournis. Cela permet d'éliminer items == null .
  • Une liste non vide a été fournie. Ceci élimine items.isEmpty .
  • Une valeur ( _selectedLocation ) a également été donné. Cela permet d'éliminer value == null . Notez que c'est DropdownButton et non pas la valeur de DropdownMenuItem La valeur de l'entreprise.

Il ne reste donc que le dernier chèque. Ça se résume à quelque chose comme :

Itérer à travers DropdownMenuItem 's. Trouvez tous ceux qui ont un value qui est égal à _selectedLocation . Ensuite, vérifiez combien d'éléments correspondant à cette valeur ont été trouvés. Il doit y avoir exactement un widget qui a cette valeur. Sinon, une erreur est générée.

La façon dont le code est présenté, il n'y a pas de DropdownMenuItem qui a une valeur de _selectedLocation . Au lieu de cela, tous les widgets ont leur valeur fixée à null . Puisque null != _selectedLocation la dernière condition échoue. Vérifiez cela en réglant _selectedLocation à null - l'application doit fonctionner.

Pour résoudre ce problème, nous devons d'abord définir une valeur pour chaque élément de la liste. DropdownMenuItem (afin que quelque chose puisse être passé à onChanged callback) :

return DropdownMenuItem(
    child: new Text(location),
    value: location,
);

L'application échouera quand même. Cela est dû au fait que votre liste ne contient toujours pas _selectedLocation La valeur de l'entreprise. Vous pouvez faire fonctionner l'application de deux manières :

  • Option 1 . Ajouter un autre widget qui a la valeur (pour satisfaire à items.where((DropdownMenuItem<T> item) => item.value == value).length == 1 ). Cela peut être utile si vous voulez permettre à l'utilisateur de re-sélectionner Please choose a location option.
  • Option 2 . Passez quelque chose à hint: parmentier et ensemble selectedLocation à null (pour satisfaire value == null condition). Utile si vous ne voulez pas Please choose a location pour rester une option.

Voir le code ci-dessous qui montre comment le faire :

import 'package:flutter/material.dart';

void main() {
  runApp(Example());
}

class Example extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
//  List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D']; // Option 1
//  String _selectedLocation = 'Please choose a location'; // Option 1
  List<String> _locations = ['A', 'B', 'C', 'D']; // Option 2
  String _selectedLocation; // Option 2

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: DropdownButton(
            hint: Text('Please choose a location'), // Not necessary for Option 1
            value: _selectedLocation,
            onChanged: (newValue) {
              setState(() {
                _selectedLocation = newValue;
              });
            },
            items: _locations.map((location) {
              return DropdownMenuItem(
                child: new Text(location),
                value: location,
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

1 votes

Merci. J'ai perdu 15 minutes à cause de cette erreur stupide. J'aimerais pouvoir donner plus de votes positifs à votre réponse :)

18voto

Rubs Points 679

vous devez tenir compte de cet élément (tiré de la documentation du DropdownButton) :

"Les éléments doivent avoir des valeurs distinctes et si la valeur n'est pas nulle, elle doit être parmi eux".

Donc, en gros, vous avez cette liste de chaînes de caractères

List<String> _locations = ['A', 'B', 'C', 'D'];

Et votre valeur dans la propriété Dropdown value est initialisée comme ceci :

String _selectedLocation = 'Please choose a location';

Essayez simplement avec cette liste :

List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D'];

Cela devrait fonctionner :)

Vérifiez également la propriété "hint". Si vous ne souhaitez pas ajouter une chaîne de caractères comme celle-ci (hors du contexte de la liste), vous pouvez opter pour quelque chose comme ceci :

DropdownButton<int>(
          items: locations.map((String val) {
                   return new DropdownMenuItem<String>(
                        value: val,
                        child: new Text(val),
                         );
                    }).toList(),
          hint: Text("Please choose a location"),
          onChanged: (newVal) {
                  _selectedLocation = newVal;
                  this.setState(() {});
                  });

9voto

DwlRathod Points 444

Vous devez ajouter value: location dans votre code pour le faire fonctionner. Vérifiez ce dehors.

items: _locations.map((String location) {
  return new DropdownMenuItem<String>(
     child: new Text(location),
     value: location,
  );
}).toList(),

7voto

Ajit Paul Points 69

Placez la valeur à l'intérieur des éléments, puis cela fonctionnera,

new DropdownButton<String>(
              items:_dropitems.map((String val){
                return DropdownMenuItem<String>(
                  value: val,
                  child: new Text(val),
                );
              }).toList(),
              hint:Text(_SelectdType),
              onChanged:(String val){
                _SelectdType= val;
                setState(() {});
                })

0 votes

Et si vous utilisez un objet personnalisé (DropdownButton<MyCustomObject>) et que cela ne fonctionne toujours pas, n'oubliez pas de remplacer l'opérateur == et le getter hashCode pour votre objet personnalisé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X