web-dev-qa-db-fra.com

Comment implémenter une liste déroulante dans le flutter?

J'ai une liste d'emplacements que je veux implémenter en tant que liste déroulante dans Flutter. Je suis assez nouveau dans la langue. 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(),

Ceci est 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'initialise comme ça.

String _selectedLocation = 'Please choose a location';

17
Chaythanya nair

Essaye ça

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

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

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

vous devez en tenir compte (à partir de la documentation DropdownButton):

"Les éléments doivent avoir des valeurs distinctes et si la valeur n’est pas nulle, il faut Être parmi eux."

Donc, fondamentalement, vous avez cette liste de chaînes

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

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

String _selectedLocation = 'Please choose a location';

Essayez juste avec cette liste:

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

Cela devrait fonctionner :)

Consultez également la propriété "hint" si vous ne souhaitez pas ajouter une chaîne comme celle-ci (en dehors du contexte de la liste), vous pouvez utiliser 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(() {});
                  });
3
Rubs

placez la valeur à l'intérieur des éléments.Ensuite, 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(() {});
                })
1
Ajit Paul

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

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

Il existe quatre conditions or. Au moins l'un d'entre eux doit être rempli:

  • Des éléments (une liste de DropdownMenuItem widgets) ont été fournis. Ceci élimine items == null.
  • Une liste non vide a été fournie. Ceci élimine items.isEmpty.
  • Une valeur (_selectedLocation) a également été donnée. Ceci élimine value == null. Notez qu'il s'agit de la valeur de DropdownButton et non de DropdownMenuItem.

Par conséquent, il ne reste que le dernier contrôle. Cela revient à quelque chose comme:

Parcourez DropdownMenuItem's. Trouvez tous ceux qui ont une value égale à _selectedLocation. Ensuite, vérifiez combien d’éléments correspondants ont été trouvés. Il doit y avoir exactement un widget qui a cette valeur. Sinon, jetez une erreur.

Le code de manière est présenté, il n'y a pas de widget DropdownMenuItem qui a la valeur _selectedLocation. Au lieu de cela, la valeur de null est définie pour tous les widgets. Depuis null != _selectedLocation, la dernière condition échoue. Vérifiez cela en définissant _selectedLocation sur null - l'application doit s'exécuter.

Pour résoudre le problème, nous devons d’abord définir une valeur pour chaque DropdownMenuItem (afin que quelque chose puisse être passé au rappel onChanged):

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

L'application échouera toujours. En effet, votre liste ne contient toujours pas la valeur de _selectedLocation. Vous pouvez faire en sorte que l'application fonctionne de deux manières:

  • Option 1 . Ajoutez 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 souhaitez laisser l'utilisateur sélectionner à nouveau l'option Please choose a location.
  • Option 2 . Passez quelque chose à hint: paremter et définissez selectedLocation sur null (pour satisfaire à la condition value == null). Utile si vous ne voulez pas que Please choose a location reste une option.

Voir le code ci-dessous qui montre comment 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(),
          ),
        ),
      ),
    );
  }
}
0
cegas

Disons que nous créons une liste déroulante de devise:

List _currency = ["INR", "USD", "SGD", "EUR", "PND"];
List<DropdownMenuItem<String>> _dropDownMenuCurrencyItems;
String _currentCurrency;

List<DropdownMenuItem<String>> getDropDownMenuCurrencyItems() {
  List<DropdownMenuItem<String>> items = new List();
  for (String currency in _currency) {
    items.add(
      new DropdownMenuItem(value: currency, child: new Text(currency)));
  }
  return items;
}

void changedDropDownItem(String selectedCurrency) {
  setState(() {
    _currentCurrency = selectedCurrency;
  });
}

Ajouter ci-dessous le code dans la partie du corps:

new Row(children: <Widget>[
  new Text("Currency: "),
  new Container(
    padding: new EdgeInsets.all(16.0),
  ),
  new DropdownButton(
    value: _currentCurrency,
    items: _dropDownMenuCurrencyItems,
    onChanged: changedDropDownItem,
  )
])
0
lavish

Lorsque je me suis posé le problème de vouloir un DropdownStringButton moins générique, je l'ai simplement créé:

dropdown_string_button.Dart

import 'package:flutter/material.Dart';
// Subclass of DropdownButton based on String only values.
// Yes, I know Flutter discourages subclassing, but this seems to be
// a reasonable exception where a commonly used specialization can be
// made more easily usable.
//
// Usage: 
// DropdownStringButton(items: ['A', 'B', 'C'], value: 'A', onChanged: (string) {})
//
class DropdownStringButton extends DropdownButton<String> {
  DropdownStringButton({
    Key key, @required List<String> items, value, hint, disabledHint,
    @required onChanged, elevation = 8, style, iconSize = 24.0, isDense = false,
    isExpanded = false, }) : 
    assert(items == null || value == null || items.where((String item) => item == value).length == 1),
        super(
          key: key,
          items: items.map((String item) {
            return DropdownMenuItem<String>(child: Text(item), value: item);
          }).toList(),
        value: value, hint: hint, disabledHint: disabledHint, onChanged: onChanged,
        elevation: elevation, style: style, iconSize: iconSize, isDense: isDense,
        isExpanded: isExpanded,
        );
    }
0
Cirec Beback

L'erreur que vous obtenez est due à demander une propriété d'un objet null. Votre élément doit être nul. Ainsi, lorsque vous demandez la comparaison de sa valeur, vous obtenez cette erreur. Vérifiez que vous obtenez des données ou que votre liste est une liste d'objets et non de simples chaînes.

0
Matias

J'étais confronté à un problème similaire avec DropDownButton lorsque j'essayais d'afficher une liste dynamique de chaînes dans la liste déroulante. J'ai fini par créer un plugin: flutter_search_panel . Pas un plugin déroulant, mais vous pouvez afficher les éléments avec la fonctionnalité de recherche.

Utilisez le code suivant pour utiliser le widget:

    FlutterSearchPanel(
        padding: EdgeInsets.all(10.0),
        selected: 'a',
        title: 'Demo Search Page',
        data: ['This', 'is', 'a', 'test', 'array'],
        icon: new Icon(Icons.label, color: Colors.black),
        color: Colors.white,
        textStyle: new TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20.0, decorationStyle: TextDecorationStyle.dotted),
        onChanged: (value) {
          print(value);
        },
   ),
0
dranzer