Как сделать AlertDialog во флаттере?

Я учусь создавать приложения во Flutter. Теперь я пришел, чтобы предупредить диалоги. Я делал это раньше в Android и iOS, но как сделать предупреждение во 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. Сохраните код диалога как виджет в отдельном файле, чтобы я мог его повторно использовать.
  2. Размытие фона при отображении диалогового окна.

Код: 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;
      },
    );
  }

Просто чтобы добавить к отличным ответам - лучший пакет, который я нашел, это:

адаптивный_диалог: ^1.8.0+1

Для одной кнопки 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'),
                                      ),
                                    ),
                                  ],
                                ),
                              ),`
Другие вопросы по тегам