Как сделать AlertDialog во флаттере?
Я учусь создавать приложения во Flutter. Теперь я пришел, чтобы предупредить диалоги. Я делал это раньше в Android и iOS, но как сделать предупреждение во Flutter?
Вот несколько связанных с этим вопросов:
- Как стилизовать действия AlertDialog во Flutter
- добавление выпадающего меню в диалоговом окне предупреждения во флаттере
- Показать диалоговое окно оповещения при загрузке главного экрана приложения автоматически
- как обновить алертилдиалог в флаттере
- Оповещение Диалог с Закругленными углами во флаттере
Я хотел бы сделать более общие канонические вопросы и ответы, поэтому мой ответ ниже.
18 ответов
Одна кнопка
showAlertDialog(BuildContext context) {
// set up the button
Widget okButton = FlatButton(
child: Text("OK"),
onPressed: () { },
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("My title"),
content: Text("This is my message."),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Две кнопки
showAlertDialog(BuildContext context) {
// set up the buttons
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget continueButton = FlatButton(
child: Text("Continue"),
onPressed: () {},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("AlertDialog"),
content: Text("Would you like to continue learning how to use Flutter alerts?"),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Три кнопки
showAlertDialog(BuildContext context) {
// set up the buttons
Widget remindButton = FlatButton(
child: Text("Remind me later"),
onPressed: () {},
);
Widget cancelButton = FlatButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget launchButton = FlatButton(
child: Text("Launch missile"),
onPressed: () {},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text("Notice"),
content: Text("Launching this missile will destroy the entire universe. Is this what you intended to do?"),
actions: [
remindButton,
cancelButton,
launchButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Обработка нажатий кнопок
onPressed
обратный вызов для кнопок в приведенных выше примерах был пустым, но вы могли бы добавить что-то вроде этого:
Widget launchButton = FlatButton(
child: Text("Launch missile"),
onPressed: () {
Navigator.of(context).pop(); // dismiss dialog
launchMissile();
},
);
Если вы сделаете обратный звонок null
, тогда кнопка будет отключена.
onPressed: null,
Дополнительный код
Вот код для main.dart
в случае, если вы не получаете функции выше для запуска.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter'),
),
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) { ... }
Я использовал аналогичный подход, но хотел
- Сохраните код диалога как виджет в отдельном файле, чтобы я мог его повторно использовать.
- Размытие фона при отображении диалогового окна.
Код:
1. alertDialog_widget.dart
import 'dart:ui';
import 'package:flutter/material.dart';
class BlurryDialog extends StatelessWidget {
String title;
String content;
VoidCallback continueCallBack;
BlurryDialog(this.title, this.content, this.continueCallBack);
TextStyle textStyle = TextStyle (color: Colors.black);
@override
Widget build(BuildContext context) {
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: AlertDialog(
title: new Text(title,style: textStyle,),
content: new Text(content, style: textStyle,),
actions: <Widget>[
new FlatButton(
child: new Text("Continue"),
onPressed: () {
continueCallBack();
},
),
new FlatButton(
child: Text("Cancel"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
));
}
}
Вы можете вызвать это в main (или где угодно), создав новый метод, например:
_showDialog(BuildContext context)
{
VoidCallback continueCallBack = () => {
Navigator.of(context).pop(),
// code on continue comes here
};
BlurryDialog alert = BlurryDialog("Abort","Are you sure you want to abort this operation?",continueCallBack);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Вы можете использовать этот фрагмент кода для создания двухкнопочного окна оповещения,
import 'package:flutter/material.dart';
class BaseAlertDialog extends StatelessWidget {
//When creating please recheck 'context' if there is an error!
Color _color = Color.fromARGB(220, 117, 218 ,255);
String _title;
String _content;
String _yes;
String _no;
Function _yesOnPressed;
Function _noOnPressed;
BaseAlertDialog({String title, String content, Function yesOnPressed, Function noOnPressed, String yes = "Yes", String no = "No"}){
this._title = title;
this._content = content;
this._yesOnPressed = yesOnPressed;
this._noOnPressed = noOnPressed;
this._yes = yes;
this._no = no;
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: new Text(this._title),
content: new Text(this._content),
backgroundColor: this._color,
shape:
RoundedRectangleBorder(borderRadius: new BorderRadius.circular(15)),
actions: <Widget>[
new FlatButton(
child: new Text(this._yes),
textColor: Colors.greenAccent,
onPressed: () {
this._yesOnPressed();
},
),
new FlatButton(
child: Text(this._no),
textColor: Colors.redAccent,
onPressed: () {
this._noOnPressed();
},
),
],
);
}
}
Чтобы показать диалог, у вас может быть метод, который вызывает его NB после импорта BaseAlertDialog
учебный класс
_confirmRegister() {
var baseDialog = BaseAlertDialog(
title: "Confirm Registration",
content: "I Agree that the information provided is correct",
yesOnPressed: () {},
noOnPressed: () {},
yes: "Agree",
no: "Cancel");
showDialog(context: context, builder: (BuildContext context) => baseDialog);
}
ВЫХОД БУДЕТ ТАК
Если вам нужен диалог только с одной кнопкой:
await showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Message'),
content: Text(
'Your file is saved.'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(); // dismisses only the dialog and returns nothing
},
child: new Text('OK'),
),
],
),
);
Если вам нужен диалог с кнопками Да / Нет:
onPressed: () async {
bool result = await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Confirmation'),
content: Text('Do you want to save?'),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(false); // dismisses only the dialog and returns false
},
child: Text('No'),
),
FlatButton(
onPressed: () {
Navigator.of(context, rootNavigator: true)
.pop(true); // dismisses only the dialog and returns true
},
child: Text('Yes'),
),
],
);
},
);
if (result) {
if (missingvalue) {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('Missing Value'),
));
} else {
saveObject();
Navigator.of(context).pop(_myObject); // dismisses the entire widget
}
} else {
Navigator.of(context).pop(_myObject); // dismisses the entire widget
}
}
Просто использовал этот настраиваемый класс диалогового окна, поле которого вам не нужно было оставлять или делать его пустым, чтобы вы легко получили эту настройку.
import 'package:flutter/material.dart';
class CustomAlertDialog extends StatelessWidget {
final Color bgColor;
final String title;
final String message;
final String positiveBtnText;
final String negativeBtnText;
final Function onPostivePressed;
final Function onNegativePressed;
final double circularBorderRadius;
CustomAlertDialog({
this.title,
this.message,
this.circularBorderRadius = 15.0,
this.bgColor = Colors.white,
this.positiveBtnText,
this.negativeBtnText,
this.onPostivePressed,
this.onNegativePressed,
}) : assert(bgColor != null),
assert(circularBorderRadius != null);
@override
Widget build(BuildContext context) {
return AlertDialog(
title: title != null ? Text(title) : null,
content: message != null ? Text(message) : null,
backgroundColor: bgColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(circularBorderRadius)),
actions: <Widget>[
negativeBtnText != null
? FlatButton(
child: Text(negativeBtnText),
textColor: Theme.of(context).accentColor,
onPressed: () {
Navigator.of(context).pop();
if (onNegativePressed != null) {
onNegativePressed();
}
},
)
: null,
positiveBtnText != null
? FlatButton(
child: Text(positiveBtnText),
textColor: Theme.of(context).accentColor,
onPressed: () {
if (onPostivePressed != null) {
onPostivePressed();
}
},
)
: null,
],
);
}
}
Применение:
var dialog = CustomAlertDialog(
title: "Logout",
message: "Are you sure, do you want to logout?",
onPostivePressed: () {},
positiveBtnText: 'Yes',
negativeBtnText: 'No');
showDialog(
context: context,
builder: (BuildContext context) => dialog);
Вывод:
Минимальный код для диалогового окна предупреждения
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('Title'),
content: Text(
'Content widget',
),
),
);
Или вы можете использовать библиотеку RFlutter Alert для этого. Это легко настраиваемый и простой в использовании. Его стиль по умолчанию включает в себя закругленные углы, и вы можете добавлять кнопки сколько угодно.
Базовое оповещение:
Alert(context: context, title: "RFLUTTER", desc: "Flutter is awesome.").show();
Оповещение с помощью кнопки:
Alert(
context: context,
type: AlertType.error,
title: "RFLUTTER ALERT",
desc: "Flutter is more awesome with RFlutter Alert.",
buttons: [
DialogButton(
child: Text(
"COOL",
style: TextStyle(color: Colors.white, fontSize: 20),
),
onPressed: () => Navigator.pop(context),
width: 120,
)
],
).show();
Вы также можете определить общие стили предупреждений.
* Я один из разработчиков RFlutter Alert.
showAlertDialog(BuildContext context, String message, String heading,
String buttonAcceptTitle, String buttonCancelTitle) {
// set up the buttons
Widget cancelButton = FlatButton(
child: Text(buttonCancelTitle),
onPressed: () {},
);
Widget continueButton = FlatButton(
child: Text(buttonAcceptTitle),
onPressed: () {
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
title: Text(heading),
content: Text(message),
actions: [
cancelButton,
continueButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
называется как:
showAlertDialog(context, 'Are you sure you want to delete?', "AppName" , "Ok", "Cancel");
Если вам нужен красивый и отзывчивый диалог предупреждений, вы можете использовать пакеты флаттера, такие как
предупреждение rflutter, необычный диалог, богатое предупреждение, приятные диалоговые окна предупреждений, простой диалог и легкое предупреждение
Эти предупреждения красивы и быстро реагируют. Среди них лучше всего rflutter alert. в настоящее время я использую оповещение rflutter для своих приложений.
Ознакомьтесь с Flutter Dropdown Banner, чтобы легко предупреждать пользователей о событиях и побуждать к действию без необходимости управлять сложностью представления, задержки и закрытия компонента.
Чтобы настроить его:
import 'packages:dropdown_banner/dropdown_banner.dart';
...
class MainApp extends StatelessWidget {
...
@override
Widget build(BuildContext context) {
final navigatorKey = GlobalKey<NavigatorState>();
...
return MaterialApp(
...
home: DropdownBanner(
child: Scaffold(...),
navigatorKey: navigatorKey,
),
);
}
}
Чтобы использовать это:
import 'packages:dropdown_banner/dropdown_banner.dart';
...
class SomeClass {
...
void doSomethingThenFail() {
DropdownBanner.showBanner(
text: 'Failed to complete network request',
color: Colors.red,
textStyle: TextStyle(color: Colors.white),
);
}
}
Щелкните здесь, чтобы увидеть пример
Если вам нужен диалог, то этот код для вас. просто используйтеshowDialog()
onPress
или любой внутри функции.
void showDialog() {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text("Login Failed!"),
content: const Text(
"Invalid credential !! Please check your email or password",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w400),
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(ctx).pop();
},
child: Container(
child: const Text(
"Try again",
style: TextStyle(color: Colors.cyan, fontSize: 17),
),
),
),
],
),
)}
Скриншоты демонстрационного диалога
надеюсь, что это полезно
Вот рабочая версия ответа Бакри Битара без изменения ее на виджет с сохранением состояния:
import 'dart:ui';
import 'package:flutter/material.dart';
class BlurryDialog extends StatelessWidget {
final String title;
final String content;
final VoidCallback continueCallBack;
final TextStyle textStyle = const TextStyle(color: Colors.black);
const BlurryDialog({
Key? key,
required this.title,
required this.content,
required this.continueCallBack,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
child: AlertDialog(
shape: RoundedRectangleBorder( // This line is added
borderRadius: BorderRadius.circular(12), // Change this value to change the corner radius
),
title: Text(title, style: textStyle, textAlign: TextAlign.center,),
content: new Text(content, style: textStyle,),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
child: Text('Yes', style: TextStyle(color: Colors.white)),
onPressed: () {
continueCallBack();
Navigator.of(context).pop();
},
style: ElevatedButton.styleFrom(
backgroundColor: Color.fromARGB(255, 54, 139, 244),
foregroundColor: Colors.black,
),
),
ElevatedButton(
child: Text('No', style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.of(context).pop();
},
style: ElevatedButton.styleFrom(
backgroundColor: Color.fromARGB(255, 54, 139, 244),
foregroundColor: Colors.black,
),
),
]),
],
),
);
}
}
Вы можете назвать это так:
VoidCallback continueCallBack = () {
Navigator.of(context).pop();
// code on continue comes here
};
BlurryDialog alert = BlurryDialog(
title: "Your Title", // Provide 'title'
content: "Your Content Text", // Provide 'content'
continueCallBack: continueCallBack, // Provide 'continueCallBack'
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
Простое и работающее решение, которое я использовал: Наслаждайтесь // Образец можно использовать для диалогового окна выхода в приложениях.
showAlertDialog(контекст BuildContext) {
Widget okButton = TextButton(
child: const Text("Leave now",style: TextStyle(color: Colors.red),),
onPressed: () { SystemNavigator.pop(); },
);
Widget nopeButton = TextButton(
child: const Text("Stay here"),
onPressed: () { Navigator.pop(context); },
);
AlertDialog alert = AlertDialog(
title: const Text("Leave"),
content: const Text("Are you sure you want to leave?"),
actions: [
nopeButton,
okButton,
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
Просто чтобы добавить к отличным ответам - лучший пакет, который я нашел, это:
Для одной кнопки OK лучшее, что я нашел, это использоватьshowOkAlertDialog
Выполнение:
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter/material.dart';
Widget build(BuildContext context) {
return Container(
child: Center(
child: IconButton(
icon: Icon(
Icons.info,
),
onPressed: () => showOkAlertDialog(
context: context,
okLabel: 'OK',
title: 'Title',
message: 'This is the message',
),
)),
);
}
Очистите и закройте, когда вы нажмете «ОК».
Другой простой вариант отображения диалогового - использовать пакет окнаstacked_services.
_dialogService.showDialog(
title: "Title",
description: "Dialog message Tex",
);
});
Это решение является общим, если вы хотите перемещаться или использовать showDialog без контекста с помощью globalKey, особенно с Bloc, или когда ваша логика отделена от вашей части пользовательского интерфейса.
Сначала установите этот пакет:
Не: я использую версию с нулевой безопасностью
get_it: ^7.2.0
Затем создайте отдельный файл для локатора вашего сервиса:
service_location.dart
import 'package:get_it/get_it.dart';
GetIt locator = GetIt.instance;
class NavigationService {
final GlobalKey<NavigatorState> navigatorKey =
new GlobalKey<NavigatorState>();
Future<dynamic> navigateTo(String routeName) {
return navigatorKey.currentState!.pushNamed(routeName);
}
void setupLocator() {
locator.registerLazySingleton(() => NavigationService());
}
void showMyDialog() {
showDialog(
context: navigatorKey.currentContext!,
builder: (context) => Center(
child: Material(
color: Colors.transparent,
child: Text('Hello'),
),
));
}
}
на main.dart:
void main() {
WidgetsFlutterBinding.ensureInitialized();
NavigationService().setupLocator();
runApp(MyApp());
}
// add navigatorKey for MaterialApp
MaterialApp(
navigatorKey: locator<NavigationService>().navigatorKey,
),
в вашем файле бизнес-логики bloc.dart определите это внутри класса блока или в любом классе, который вы хотите использовать для навигации внутри. Затем начните перемещаться внутри любой функции внутри.
class Cubit extends Cubit<CubitState> {
final NavigationService _navigationService = locator<NavigationService>();
void sampleFunction(){
_navigationService.navigateTo('/home_screen'); // to navigate
_navigationService.showMyDialog(); // to show dialog
}
}
Не: я использую generateRoute для маршрутизации.
Этот код работает и демонстрирует, как получить значение кнопки, нажатой пользователем:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const Center(
child: MyStatelessWidget(),
),
),
);
}
}
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: () {
// set up the buttons
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () => Navigator.pop(context, 'Cancel'),
);
Widget continueButton = TextButton(
child: Text("Ok"),
onPressed: () => Navigator.pop(context, 'Ok'),
);
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('AlertDialog Title'),
content: const Text('AlertDialog description'),
actions: <Widget>[
cancelButton,
continueButton,
],
),
).then((value) => print(value));
},
child: const Text('Show Dialog'),
);
}
}
`showDialog<String>(
context: context,
builder: (BuildContext context) =>
AlertDialog(
title: const Text(
'Invalid Password',
style: TextStyle(color: Colors.red),
),
content:
const Text('Create Strong Password'),
actions: <Widget>[
Center(
child: TextButton(
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors
.red, // Background Color
),
onPressed: () => Navigator.pop(
context, 'Cancel'),
child: const Text('Cancel'),
),
),
],
),
),`