comment afficher un widget comme un popup

Sep 22 2020

Actuellement, j'ai une vue en grille. Lorsque j'appuie dessus, je navigue vers une autre page à l'aide d'un widget héros.

Sur cette page, j'ai juste un conteneur qui affiche des informations sur cette tuile de grille.

Ce que je veux, c'est que ce conteneur apparaisse au-dessus de la vue grille au lieu d'être une page différente.

Comment puis-je le faire apparaître comme ça? Et si possible, je préfère garder l'animation du héros.

Réponses

1 Nonstapp Sep 22 2020 at 15:34

Vous devez utiliser la méthode showDialog, comme ceci:

InkWell(
 child: GridItem(),
 onTap: () {
  showDialog(
   context: context,
     builder: (context) => AlertDialog(
      content: Hero(child: Card(child: YourWidget()))
     ); // you can use SimpleDialog, specify barrier dismissible etc
 },
)

Voici le lien sur la classe de dialogue https://api.flutter.dev/flutter/material/Dialog-class.html

À propos du héros, je ne suis pas sûr, car je l'écris comme de la tête, mais cela devrait faire l'affaire (souvent, ajoutez la même balise, vous n'avez pas besoin du parent de la carte si votre widget en a déjà un - Hero nécessite un widget matériel )

1 Eren Sep 22 2020 at 17:41

Je poste ce que j'ai fini par faire parce que ça marche.

Ce que @Nonstapp et @Parth ont suggéré fonctionne à l'exception de la transition Hero puisqu'elle s'applique uniquement aux PageRoutes.

Par conséquent, j'ai trouvé une autre façon d'afficher une fenêtre contextuelle similaire avec un PageRoute.

Le widget d'information que j'affiche:

return Padding(
  padding: EdgeInsets.fromLTRB(
      MediaQuery.of(context).size.width / 8,
      MediaQuery.of(context).size.height / 4,
      MediaQuery.of(context).size.width / 8,
      0),
  child: Material(
    color: Colors.transparent,
    child: ...

Le remplissage est évidemment pour le positionnement et le widget Material doit lui donner un style Material et des widgets activés comme IconButton. Donnez au widget Matériau une couleur transparente.

Voici comment je l'appelle:

void seeDetails(BuildContext context, Book book) {
    Navigator.push(
      context,
      PageRouteBuilder(
        fullscreenDialog: true,
        opaque: false,
        pageBuilder: (_, __, ___) => ChangeNotifierProvider.value(
          value: book,
          child: DetailCard(),
        ),
      ),
    );
  }

J'utilise le PageRouter pour afficher une boîte de dialogue en plein écran mais en raison de mes paramètres là-haut, seule la carte d'information est visible.

L'inconvénient est que je ne peux pas activer barrièreDismissibles puisque je suis sur un autre guichet automatique.

Voici mon résultat:

Cependant, la vraie solution est ce que @pskink a suggéré ci-dessus. Cela nécessite plus de configuration et d'ajustements et j'ai eu des problèmes avec les fournisseurs. Voici comment vous pouvez l'implémenter

ParthPitroda Sep 22 2020 at 15:23

vous pouvez utiliser une boîte de dialogue personnalisée: -

onPressed: () {
        showDialog(
            context: context,
            builder: (_) => Center(
          child: RaisedButton(
            child: Text("Show dialog"),
            onPressed: () {
              showDialog(
                context: context,
                builder: (context) {
                  return Dialog(
                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
                    elevation: 16,
                    child: Container(
                      height: 400.0,
                      width: 360.0,
                      child: ListView(
                        children: <Widget>[
                          SizedBox(height: 20),
                          Center(
                            child: Text(
                              "Leaderboard",
                              style: TextStyle(fontSize: 24, color: Colors.blue, fontWeight: FontWeight.bold),
                            ),
                          ),
                          SizedBox(height: 20),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 1", score: 1000),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 2", score: 2000),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 3", score: 3000),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 4", score: 4000),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 5", score: 5000),
                          _buildName(imageAsset: 'assets/chocolate.jpg', name: "Name 6", score: 6000),
                        ],
                      ),
                    ),
                  );
                },
              );
            },
          ),
        ),
        );
    }
    
    
    Widget _buildName({String imageAsset, String name, double score}) {
      return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20.0),
        child: Column(
          children: <Widget>[
            SizedBox(height: 12),
            Container(height: 2, color: Colors.redAccent),
            SizedBox(height: 12),
            Row(
              children: <Widget>[
                CircleAvatar(
                  backgroundImage: AssetImage(imageAsset),
                  radius: 30,
                ),
                SizedBox(width: 12),
                Text(name),
                Spacer(),
                Container(
                  padding: EdgeInsets.symmetric(vertical: 8, horizontal: 20),
                  child: Text("${score}"),
                  decoration: BoxDecoration(
                    color: Colors.yellow[900],
                    borderRadius: BorderRadius.circular(20),
                  ),
                ),
              ],
            ),
          ],
        ),
      );
    }