Show Dialog in Flutter mit Callback Funktion
Vor kurzem hatte ich in diesem Blog einen Post über AlertDialog(...) geschrieben.
In diesem Zusammenhang bin ich dort auf, ShowDialog(...) gestossen. Es ist also keine schlechte Idee diese Funktion näher zu betrachten.
Im Zusammenhang mit AlertDialog(...) haben wir die Frage, was passiert wenn der Button gedrückt wurde, noch damit beantwortet, das der Anwender zurück auf den ursprünglichen Schirm kam.
In einer realen Anwendung wird man aber in der Regel zwei Buttons haben, ok und cancel zum Beispiel. Wir müssen diese zwei Buttons auswerten können.
Grundlagen
Ein Dialog in Flutter schwebt über allen anderen Bildschirmelementen. Er kann Buttons, aber auch zum Beispiel ein Bild, enthalten. Als Grundeinstellung wird der Hintergrund abgedunkelt.
Um effektiv auf die Buttons reagieren zu können, benötigen wir ein Statefull Widget. Ich werde in diesem Post nicht weiter auf dieses Widget eingehen. In diesem Blog, aber auch im Internet, finden sich genug Informationen dazu.
Wenn Du Flutter und damit auch Dart benutzt wirst Du des Öfteren auf Callback Funktionen treffen. Eine Funktion kann als Parameter auch eine andere Funktion übernehmen. Ein Beispiel:
class Demo{ final String text; final String text2; final void Function(bool v) callBack; Demo({required this.text,required this.text2,required this.callBack}); }
Der Code oben: Die Klasse Demo erwartet u. A. als Parameter eine Funktion callback. Mit bool v definieren wir, das diese Callback Funktion vom Typ bool ist, also wahr oder falsch.
Der Code
Starten wir mit dem Einstieg:
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Flutter Demo', home: HomePage(), ); } } class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { String message = ''; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(message, style: const TextStyle(color: Colors.black, fontSize: 30)), const SizedBox(height: 18), TextButton( style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.green)), onPressed: onTapShowDialog, child: const Text( 'Show Dialog Widget', style: TextStyle(color: Colors.white), ), ), ], ), ), ); }
onTapShowDialog
Nachdem der Auslöser betätigt wurde, kommt diese Funktion zum Einsatz:
void onTapShowDialog() { showAlertDialogs( context, title: 'Ein Flutter Demo', content: 'Für Testzwecke', ).then((value) { setState(() { if (value == true) { message = '[Yes] wurde benutzt!!!'; } else if (value == false) { message = '[NO] wurde benutzt!!!'; } else { message = '[Nichts] wurde benutzt!!!'; } }); debugPrint(value.toString()); }); } }
Der "wichtige" Abschnitt beginnt mit .then(...) ! showAlertDialogs(...) retourniert einen Future !
Sobald das Resultat dieses Future's vorliegt (value), wird der Code im .then(...) Abschnitt ausgeführt. Dabei wird value ausgewertet und in der setState(...) Funktion wird abhängig davon die Zeichenkette message gesetzt.
Mit debugPrint(...) drucken wir zur Kontrolle den Wert in die Konsole.
showAlertDialogs
Wie oben schon geschrieben retourniert diese Funktion einen Future:
Future<bool?> showAlertDialogs(BuildContext context, {required String title, required String content}) async { bool? response; await showDialog( context: context, builder: (context) => MeinAlertDialog( title: title, inhalt: content, buttonText1: 'Yes', buttonText2: 'No', callback: (bool v) { response = v; }, ), ); return response; }
Als Parameter für builder: übergeben wir MeinAlertDialog(...). Hier müssen wir auch die CallBack Funktion mit übergeben. Sie wird einen bool Wert liefern, der response zugewiesen wird. Am Schluss wird response an die aufrufende Ebene retourniert. Im übrigen wird die Variable response, dadurch das sie nicht initialisiert wird, zu Beginn NULL zugewiesen.
Der Hauptteil der Arbeit wir aber im folgenden Code ausgeführt:
MeinAlertDialog
class MeinAlertDialog extends StatelessWidget { final String title; final String inhalt; final String buttonText1; final String? buttonText2; final void Function(bool v) callback; const MeinAlertDialog( {Key? key, required this.title, required this.inhalt, required this.buttonText1, this.buttonText2, required this.callback}) : super(key: key); @override Widget build(BuildContext context) { return AlertDialog( title: Text(title), content: Text(inhalt), actions: <Widget>[ TextButton( style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.green)), child: Text(buttonText1, style: const TextStyle(color: Colors.white)), onPressed: () { ///Wenn der Benutzer YES drückt callback(true); Navigator.pop(context); }, ), TextButton( child: Text("$buttonText2", style: const TextStyle(color: Colors.black)), onPressed: () { ///Wenn der Benutzer NO drückt callback(false); Navigator.pop(context); }, ), ], ); } }
Dieser Artikel basiert im übrigen auf einem Post von Paul Edeme’kong.
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const MaterialApp( title: 'Flutter Demo', home: HomePage(), ); } } class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { String message = ''; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(message, style: const TextStyle(color: Colors.black, fontSize: 30)), const SizedBox(height: 18), TextButton( style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.green)), onPressed: onTapShowDialog, child: const Text( 'Show Dialog Widget', style: TextStyle(color: Colors.white), ), ), ], ), ), ); } void onTapShowDialog() { showAlertDialogs( context, title: 'Ein Flutter Demo', content: 'Für Testzwecke', ).then((value) { setState(() { if (value == true) { message = '[Yes] wurde benutzt!!!'; } else if (value == false) { message = '[NO] wurde benutzt!!!'; } else { message = '[Nichts] wurde benutzt!!!'; } }); debugPrint(value.toString()); }); } } class MeinAlertDialog extends StatelessWidget { final String title; final String inhalt; final String buttonText1; final String? buttonText2; final void Function(bool v) callback; const MeinAlertDialog( {Key? key, required this.title, required this.inhalt, required this.buttonText1, this.buttonText2, required this.callback}) : super(key: key); @override Widget build(BuildContext context) { return AlertDialog( title: Text(title), content: Text(inhalt), actions: <Widget>[ TextButton( style: ButtonStyle(backgroundColor: MaterialStateProperty.all(Colors.green)), child: Text(buttonText1, style: const TextStyle(color: Colors.white)), onPressed: () { ///Wenn der Benutzer YES drückt callback(true); Navigator.pop(context); }, ), TextButton( child: Text("$buttonText2", style: const TextStyle(color: Colors.black)), onPressed: () { ///Wenn der Benutzer NO drückt callback(false); Navigator.pop(context); }, ), ], ); } } Future<bool?> showAlertDialogs(BuildContext context, {required String title, required String content}) async { bool? response; await showDialog( context: context, builder: (context) => MeinAlertDialog( title: title, inhalt: content, buttonText1: 'Yes', buttonText2: 'No', callback: (bool v) { response = v; }, ), ); return response; }
Kommentare
Kommentar veröffentlichen