222 votes

Comment créer un toast dans Flutter

Puis-je créer quelque chose de similaire à Toasts dans Flutter ?

Juste une minuscule fenêtre de notification qui n'est pas directement dans le visage de l'utilisateur et qui ne verrouille pas ou n'estompe pas la vue derrière elle.

278voto

Rémi Rousselet Points 45139

UPDATE : Scaffold.of(context).showSnackBar est déprécié dans Flutter 2.0.0 (stable)

Vous pouvez accéder au parent ScaffoldMessengerState en utilisant ScaffoldMessenger.of(context) .

Ensuite, faites quelque chose comme

ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Sending Message"),
    ));

Les Snackbars sont les "Toast" officiels du Material Design. Voir Snackbars .

Voici un exemple qui fonctionne parfaitement :

Enter image description here

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  const Home({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Snack bar'),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () => _showToast(context),
          child: const Text('Show toast'),
        ),
      ),
    );
  }

  void _showToast(BuildContext context) {
    final scaffold = ScaffoldMessenger.of(context);
    scaffold.showSnackBar(
      SnackBar(
        content: const Text('Added to favorite'),
        action: SnackBarAction(label: 'UNDO', onPressed: scaffold.hideCurrentSnackBar),
      ),
    );
  }
}

3 votes

Comment cela doit-il être intégré dans un onPressed par exemple ? J'ai essayé et rien ne s'affiche à l'écran.

1 votes

Eh bien, je ne suis jamais rentré dans le moule et je sais que "officiel" ne veut pas dire absolu ! !! La Snackbar n'est pas du tout adaptée à l'interface utilisateur de mon application, c'est pourquoi je ne l'utilise pas et je mets toujours en place les anciennes notifications flottantes de type popup. Je pense qu'il est très facile pour les utilisateurs de rater les notifications de la Snackbar (surtout s'ils n'y sont pas habitués) ; mais il n'est pas facile de rater une popup flottant au milieu, en haut ou en bas de l'écran.

1 votes

@aziza enveloppez votre widget de bouton dans Builder(), cela fonctionnera.

116voto

Raouf Rahiche Points 4482

Utilisez ce plugin

Fluttertoast.showToast(
        msg: "This is Toast messaget",
        toastLength: Toast.LENGTH_SHORT,
        gravity: ToastGravity.CENTER,
        timeInSecForIos: 1
    );

enter image description here

3 votes

Vous devez d'abord ajouter la dépendance Fluttertoast dans le fichier pubspec.yaml. Le lien vers la dépendance est ici [link] ( pub.dartlang.org/packages/fluttertoast ). Vous pouvez alors utiliser le code ci-dessus

2 votes

Unhandled Exception: MissingPluginException(No implementation found for method showToast on channel PonnamKarthik/fluttertoast)

1 votes

Maintenant cela fonctionne, je dois arrêter l'application et la lancer sans déboguer :)

79voto

Collin Jackson Points 29995

SnackBar est définitivement la bonne classe à utiliser, comme l'a souligné Darky.

Snackbar

Une chose délicate à propos de showSnackBar est d'arriver à la ScaffoldState si vous essayez d'appeler showSnackBar dans la méthode de construction où vous construisez votre Scaffold .

Vous verrez peut-être une erreur comme celle-ci, qui comprend un texte expliquant comment résoudre le problème.

 EXCEPTION CAUGHT BY GESTURE 
The following assertion was thrown while handling a gesture:
Scaffold.of() called with a context that does not contain a Scaffold.
No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This
usually happens when the context provided is from the same StatefulWidget as that whose build
function actually creates the Scaffold widget being sought.
There are several ways to avoid this problem. The simplest is to use a Builder to get a context that
is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of():
  https://docs.flutter.io/flutter/material/Scaffold/of.html
A more efficient solution is to split your build function into several widgets. This introduces a
new context from which you can obtain the Scaffold. In this solution, you would have an outer widget
that creates the Scaffold populated by instances of your new inner widgets, and then in these inner
widgets you would use Scaffold.of().
A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the
key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.
The context used was:
  MyHomePage
When the exception was thrown, this was the stack:
#0      Scaffold.of (package:flutter/src/material/scaffold.dart:444:5)
#1      MyHomePage.build.<anonymous closure> (/Users/jackson/Library/Developer/CoreSimulator/Devices/7072C907-DBAD-44FE-8F40-0257442C51D9/data/Containers/Data/Application/77FEC1A4-1453-442C-8208-96E0323DEFB2/tmp/so_scratch2Tkq9Jb/so_scratch2/lib/main.dart:23:24)
#2      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:323:14)
#3      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:375:30)
#4      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
#5      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:149:9)
#6      TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:119:7)
#7      GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
#8      BindingBase&SchedulerBinding&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:147:20)
#9      BindingBase&SchedulerBinding&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
#10     BindingBase&SchedulerBinding&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
#11     BindingBase&SchedulerBinding&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
#12     BindingBase&SchedulerBinding&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
#13     _invoke1 (file:///b/build/slave/Mac_Engine/build/src/flutter/lib/ui/hooks.dart:100)
#14     _dispatchPointerDataPacket (file:///b/build/slave/Mac_Engine/build/src/flutter/lib/ui/hooks.dart:58)
Handler: onTap
Recognizer:
  TapGestureRecognizer#69dbc(debugOwner: GestureDetector, state: ready)

Vous pouvez soit passer un GlobalKey à votre Scaffold constructeur :

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final key = new GlobalKey<ScaffoldState>();
    return new Scaffold(
      key: key,
      floatingActionButton: new Builder(
        builder: (BuildContext context) {
          return new FloatingActionButton(
            onPressed: () {
              key.currentState.showSnackBar(new SnackBar(
                content: new Text("Sending Message"),
              ));
            },
            tooltip: 'Increment',
            child: new Icon(Icons.add),
          );
        }
      ),
    );
  }
}

Ou vous pouvez utiliser un Builder pour créer un BuildContext qui est un enfant de l'échafaudage.

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      floatingActionButton: new Builder(
        builder: (BuildContext context) {
          return new FloatingActionButton(
            onPressed: () {
              Scaffold.of(context).showSnackBar(new SnackBar(
                content: new Text("Sending Message"),
              ));
            },
            tooltip: 'Increment',
            child: new Icon(Icons.add),
          );
        }
      ),
    );
  }
}

Enfin, vous pourriez diviser votre widget en plusieurs classes, ce qui constitue la meilleure approche à long terme.

0 votes

J'ai essayé GlobalKey, mais j'obtiens maintenant cette exception : I/flutter ( 4965): The following assertion was thrown while handling a gesture: I/flutter ( 4965): type 'LabeledGlobalKey<ScaffoldState>' is not a subtype of type 'BuildContext' of 'context' where I/flutter ( 4965): LabeledGlobalKey is from package:flutter/src/widgets/framework.dart I/flutter ( 4965): ScaffoldState is from package:flutter/src/material/scaffold.dart I/flutter ( 4965): Scaffold is from package:flutter/src/material/scaffold.dart I/flutter ( 4965): BuildContext is from package:flutter/src/widgets/framework.dart

1 votes

Il semble que vous utilisiez un GlobalKey comme argument lorsqu'un BuildContext est attendu. Je ne peux pas vous aider à déboguer davantage sans voir plus de votre code. Veuillez poster la ligne de code qui lève l'exception. Vous n'utilisez probablement pas les bons arguments.

2 votes

Je peux confirmer qu'en utilisant le Builder L'option que vous avez proposée fonctionne bien. J'ai rencontré ce problème et cela l'a résolu pour moi.

17voto

Virendra Varma Points 350

Pour afficher un message Toast, vous pouvez utiliser le plugin FlutterToast. Pour utiliser ce plugin, vous devez :

  1. Ajoutez cette dépendance à votre pubspec.yaml fichier : fluttertoast: ^3.1.0
  2. Pour obtenir le paquet, vous devez exécuter cette commande : $ flutter packages get
  3. importer le paquet : import 'package:fluttertoast/fluttertoast.dart';

Utilisez-le comme ça :

Fluttertoast.showToast(
    msg: "your message",
    toastLength: Toast.LENGTH_SHORT,
    gravity: ToastGravity.BOTTOM // Also possible "TOP" and "CENTER"
    backgroundColor: "#e74c3c",
    textColor: '#ffffff');

Pour plus d'informations, consultez ce .

7voto

user2179571 Points 15

Je voudrais proposer une solution alternative à l'utilisation du package barre de flottaison .

Comme le disait l'emballage : Utilisez ce paquet si vous avez besoin de plus de personnalisation lors de la notification de votre utilisateur. Pour les développeurs Android, il est fait pour remplacer les toasts et les snacks.

Une autre suggestion pour utiliser la flushbar est Comment puis-je afficher un snackbar après navigator.pop(context) dans Flutter ?

Vous pouvez également définir FlushbarPosition sur TOP ou BOTTOM :

Enter image description here

    Flushbar(
      title: "Hey Ninja",
      message: "Lorem Ipsum is simply dummy text of the printing and typesetting industry",
      flushbarPosition: FlushbarPosition.TOP,
      flushbarStyle: FlushbarStyle.FLOATING,
      reverseAnimationCurve: Curves.decelerate,
      forwardAnimationCurve: Curves.elasticOut,
      backgroundColor: Colors.red,
      boxShadows: [BoxShadow(color: Colors.blue[800], offset: Offset(0.0, 2.0), blurRadius: 3.0)],
      backgroundGradient: LinearGradient(colors: [Colors.blueGrey, Colors.black]),
      isDismissible: false,
      duration: Duration(seconds: 4),
      icon: Icon(
        Icons.check,
        color: Colors.greenAccent,
      ),
      mainButton: FlatButton(
        onPressed: () {},
        child: Text(
          "CLAP",
          style: TextStyle(color: Colors.amber),
        ),
      ),
      showProgressIndicator: true,
      progressIndicatorBackgroundColor: Colors.blueGrey,
      titleText: Text(
        "Hello Hero",
        style: TextStyle(
            fontWeight: FontWeight.bold, fontSize: 20.0, color: Colors.yellow[600], fontFamily: "ShadowsIntoLightTwo"),
      ),
      messageText: Text(
        "You killed that giant monster in the city. Congratulations!",
        style: TextStyle(fontSize: 18.0, color: Colors.green, fontFamily: "ShadowsIntoLightTwo"),
      ),
    )..show(context);

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