web-dev-qa-db-fra.com

Flutter: ListView dans un SimpleDialog

Je veux montrer un SimpleDialog avec ListView.builder dans mon application Flutter avec ce code: 

showDialog(
  context: context,
  builder: (BuildContext context) {
    return new SimpleDialog(
      children: <Widget>[
        new FittedBox(
          child: new ListView(
            children: <Widget>[
              new Text("one"),
              new Text("two"),
            ],
          ),
        )
      ],
    );
  },
);

ce qui donne cette erreur (désolé, je ne pouvais pas envelopper les journaux sous forme de code car Stackoverflow se plaint qu'il y a trop de code):

══╡ EXCEPTION PRISE EN RENDU DE BIBLIOTHEQUE I/flutter (4481): L'assertion suivante a été émise lors de performLayout (): I/flutter (4481): RenderViewport ne prend pas en charge le retour des dimensions intrinsèques . I/flutter (4481): Pour calculer les dimensions intrinsèques, il faudrait instancier chaque enfant de la fenêtre de visualisation, ce qui I/flutter (4481): permet de s'affranchir du point de vue des fenêtres . I/flutter (4481): Si vous essayez simplement de réduire la fenêtre d'affichage dans la direction de l'axe principal, considérez a I/flutter (4481): objet de rendu RenderShrinkWrappingViewport (widget ShrinkWrappingViewport), qui permet d'atteindre cet objectif I/flutter (4481): effet sans implémentation de la dimension intrinsèque API . I/flutter (4481): ... I/flutter (4481): Une autre exception a été émise: RenderBox n'a pas été défini: RenderPhysicalShape # 83d92 relayoutBoundary = up2 NEEDS-Paint I/flutter (4481): Une autre exception a été levée: 'package: flutter/src/rendering/shifted_box.Dart': Échec de l'assertion: ligne 310 pos 12: 'child.hasSize': n'est pas vrai . I/flutter (4481): Une autre exception a été émise: RenderBox n'a pas été défini: RenderPhysicalShape # 83d92 relayoutBoundary = up2

J'ai essayé d'utiliser Container avec une hauteur et une largeur spécifiques, et cela fonctionne, mais je veux que ListView s'adapte à lui-même dans la boîte de dialogue.

Comment inclure un ListView dans un SimpleDialog?

5
Darkhan

Just warp ListView.builder to Container et définissez height et width de Container.

Comme ci-dessous!

Widget setupAlertDialoadContainer() {
    return Container(
      height: 300.0, // Change as per your requirement
      width: 300.0, // Change as per your requirement
      child: ListView.builder(
        shrinkWrap: true,
        itemCount: 5,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text('Gujarat, India'),
          );
        },
      ),
    );
  }

Et appelez la méthode ci-dessus dans showDialog.

showDialog(
   context: context,
   builder: (BuildContext context) {
   return AlertDialog(
       title: Text('Country List'),
       content: getAllSelectedCountry(),
   );
  }
);
2
Govaadiyo

Ceci est une réponse plus générale pour les futurs visiteurs.

Comment créer un dialogue avec une liste

Si vous souhaitez un dialogue avec un ListView, vous devez envisager un SimpleDialog . Un SimpleDialog est conçu pour afficher les options dans une liste (par opposition à un AlertDialog , destiné à informer l'utilisateur de quelque chose).

Voici un exemple simple:

enter image description here

Le processus de création d'un SimpleDialog est fondamentalement identique à celui d'un AlertDialog (ils sont tous deux basés sur Dialog), sauf que vous définissez des widgets d'élément de liste appelés SimpleDialogOptions au lieu de boutons. Lorsque vous appuyez sur une option de liste, un rappel est déclenché et vous pouvez y répondre.

  // set up the list options
  Widget optionOne = SimpleDialogOption(
    child: const Text('horse'),
    onPressed: () {},
  );
  Widget optionTwo = SimpleDialogOption(
    child: const Text('cow'),
    onPressed: () {},
  );
  Widget optionThree = SimpleDialogOption(
    child: const Text('camel'),
    onPressed: () {},
  );
  Widget optionFour = SimpleDialogOption(
    child: const Text('sheep'),
    onPressed: () {},
  );
  Widget optionFive = SimpleDialogOption(
    child: const Text('goat'),
    onPressed: () {},
  );

  // set up the SimpleDialog
  SimpleDialog dialog = SimpleDialog(
    title: const Text('Choose an animal'),
    children: <Widget>[
      optionOne,
      optionTwo,
      optionThree,
      optionFour,
      optionFive,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return dialog;
    },
  );

Gestion des presses d'option

Lorsqu'un utilisateur clique sur un élément, vous pouvez fermer la boîte de dialogue et effectuer une action.

  Widget optionOne = SimpleDialogOption(
    child: const Text('horse'),
    onPressed: () {
      Navigator.of(context).pop();
      _doSomething();
    },
  );

Remarques

Code

Voici le code complet pour l'exemple ci-dessus.

main.Dart

import 'package:flutter/material.Dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SimpleDialog',
      home: Scaffold(
          appBar: AppBar(
            title: Text('SimpleDialog'),
          ),
          body: MyLayout()),
    );
  }
}

class MyLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: RaisedButton(
        child: Text('Show alert'),
        onPressed: () {
          showAlertDialog(context);
        },
      ),
    );
  }
}

// replace this function with the examples above
showAlertDialog(BuildContext context) {

  // set up the list options
  Widget optionOne = SimpleDialogOption(
    child: const Text('horse'),
    onPressed: () {
      print('horse');
      Navigator.of(context).pop();
    },
  );
  Widget optionTwo = SimpleDialogOption(
    child: const Text('cow'),
    onPressed: () {
      print('cow');
      Navigator.of(context).pop();
    },
  );
  Widget optionThree = SimpleDialogOption(
    child: const Text('camel'),
    onPressed: () {
      print('camel');
      Navigator.of(context).pop();
    },
  );
  Widget optionFour = SimpleDialogOption(
    child: const Text('sheep'),
    onPressed: () {
      print('sheep');
      Navigator.of(context).pop();
    },
  );
  Widget optionFive = SimpleDialogOption(
    child: const Text('goat'),
    onPressed: () {
      print('goat');
      Navigator.of(context).pop();
    },
  );

  // set up the SimpleDialog
  SimpleDialog dialog = SimpleDialog(
    title: const Text('Choose an animal'),
    children: <Widget>[
      optionOne,
      optionTwo,
      optionThree,
      optionFour,
      optionFive,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return dialog;
    },
  );
}
0
Suragch

J'ai trouvé un moyen ... Bien que ce soit un peu hacky, et donc il pourrait y avoir une meilleure option.

Vous aurez besoin de ce paquet:

import 'package:flutter/services.Dart';

Créez le widget:

class MyDialog extends StatefulWidget {
  MyDialog ({Key key}) : super(key: key);
  MyDialogState createState() => new MyDialogState();
}
class MyDialogState extends State<MyDialog> {

Si l'écran pivote, cela gâche tout parce que la boîte de dialogue conserve sa taille d'origine. Vous pouvez probablement résoudre ce problème avec un peu d'effort, mais je le verrouille pour empêcher la rotation, comme ceci:

  @override
  initState() { super.initState();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
  }

Puis je le déverrouille comme ceci à la fin:

  @override
  dispose() { super.dispose();
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.landscapeRight,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);
  }

Cela empêche donc le dialogue de tout gâcher. Ensuite, je reçois la taille et la largeur de l'écran dans la méthode de construction:

@override
Widget build(BuildContext context) {
  double width = MediaQuery.of(context).size.width;
  double height = MediaQuery.of(context).size.height;

Puis suivi avec cette mise en page:

 return ConstrainedBox(
    constraints: BoxConstraints(maxHeight: height, maxWidth: width),
    child: Column(
      children: <Widget>[
        Expanded(
          child: GridView.count(
            primary: false,
            padding: const EdgeInsets.all(20.0),
            crossAxisSpacing: 10.0,
            crossAxisCount: 3,
            children: _images
          )
        ),
      ]
    ),
  );
}

..again, je ne pense pas que ce soit le meilleur, mais cela a fonctionné pour moi jusqu'à présent.

0
Jus10

vous pouvez créer une méthode séparée pour le code SimpleDialogOptions ci-dessous:

final SimpleDialog dialog = new SimpleDialog(
      title: const Text('Select assignment'),
      children: <Widget>[
        new SimpleDialogOption(
          onPressed: () { Navigator.pop(context); },
          child: const Text('Text one'),
        ),
        new SimpleDialogOption(
          onPressed: () {},
          child: const Text('Text two'),
        ),
      ],
    );
    return dialog;
0
silentsudo