mirror of
https://github.com/Iconica-Development/flutter_dialogs.git
synced 2025-05-18 19:03:43 +02:00
feat: add all elements from flutter_bottom_alert_dialog to the component
This commit is contained in:
parent
c29575cff2
commit
586174c264
7 changed files with 775 additions and 11 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
## 1.0.0
|
||||||
|
- Flutter_dialogs and flutter_bottom_alert_dialogs combined into one package
|
||||||
|
|
||||||
## 0.0.2
|
## 0.0.2
|
||||||
|
|
||||||
- Added CI and linter
|
- Added CI and linter
|
||||||
|
|
|
@ -6,11 +6,11 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_dialogs/flutter_dialogs.dart';
|
import 'package:flutter_dialogs/flutter_dialogs.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(const MyApp());
|
runApp(const DialogDemoApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class DialogDemoApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
const DialogDemoApp({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -19,21 +19,26 @@ class MyApp extends StatelessWidget {
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
),
|
),
|
||||||
home: const MyHomePage(title: 'Flutter Dialogs demo'),
|
home: const DialogDemoPage(title: 'Flutter Dialogs demo'),
|
||||||
|
builder: (context, child) {
|
||||||
|
return BottomAlertDialogConfig(
|
||||||
|
child: child ?? const SizedBox.shrink(),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class DialogDemoPage extends StatefulWidget {
|
||||||
const MyHomePage({super.key, required this.title});
|
const DialogDemoPage({super.key, required this.title});
|
||||||
|
|
||||||
final String title;
|
final String title;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MyHomePage> createState() => _MyHomePageState();
|
State<DialogDemoPage> createState() => _DialogDemoPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _DialogDemoPageState extends State<DialogDemoPage> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -103,11 +108,339 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
),
|
),
|
||||||
const Spacer(
|
const Spacer(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
)
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.singleButton(
|
||||||
|
closeButton: true,
|
||||||
|
title: const Text('Confirm'),
|
||||||
|
body: const Text(
|
||||||
|
'Click the button to dismiss',
|
||||||
|
),
|
||||||
|
buttonText: 'Ok',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.singleButton'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.multiButton(
|
||||||
|
title: const Text('Favorite Color'),
|
||||||
|
body: const Text(
|
||||||
|
'Choose your favorite color',
|
||||||
|
),
|
||||||
|
buttons: [
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Red',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
buttonType: ButtonType.primary,
|
||||||
|
),
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Green',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
buttonType: ButtonType.primary,
|
||||||
|
),
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Blue',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
buttonType: ButtonType.primary,
|
||||||
|
),
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Yellow',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
buttonType: ButtonType.primary,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.multiButton'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.singleButtonIcon(
|
||||||
|
closeButton: true,
|
||||||
|
title: const Text('Confirm'),
|
||||||
|
body: const Text(
|
||||||
|
'Click the button to dismiss',
|
||||||
|
),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.info,
|
||||||
|
color: Colors.blue,
|
||||||
|
),
|
||||||
|
buttonText: 'Ok',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.singleButtonIcon'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.icon(
|
||||||
|
closeButton: true,
|
||||||
|
title: const Text('Favorite Car'),
|
||||||
|
body: const Text(
|
||||||
|
'Choose your favorite car brand',
|
||||||
|
),
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.car_rental_sharp,
|
||||||
|
),
|
||||||
|
buttons: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text('BMW'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text('Opel'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text('Mercedes'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text('Kia'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
child: const Text('Skoda'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.icon'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.yesOrNo(
|
||||||
|
title: const Text('Question'),
|
||||||
|
body: const Text(
|
||||||
|
'Do you really wanna do this?',
|
||||||
|
),
|
||||||
|
onYes: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
onNo: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.yesOrNo'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.yesOrNoIcon(
|
||||||
|
title: const Text('Question'),
|
||||||
|
body: const Text(
|
||||||
|
'Do you really wanna do this?',
|
||||||
|
),
|
||||||
|
onYes: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
onNo: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.question_mark_sharp,
|
||||||
|
color: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.yesOrNoIcon'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.custom(
|
||||||
|
closeButton: true,
|
||||||
|
body: SizedBox(
|
||||||
|
height: 100,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Text('Custom Dialog with PageView'),
|
||||||
|
Flexible(
|
||||||
|
child: PageView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child:
|
||||||
|
const Center(child: Text('Page 1')),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child:
|
||||||
|
const Center(child: Text('Page 2')),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child:
|
||||||
|
const Center(child: Text('Page 3')),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
buttons: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text('Ok'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('BottomAlertDialog.custom'),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
child: const Text('Multiple chained dialogs'),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BottomAlertDialog.yesOrNo(
|
||||||
|
closeButton: true,
|
||||||
|
title: const Text('Pokémon'),
|
||||||
|
body: const Text(
|
||||||
|
'Do you want to choose your starter Pokémon?',
|
||||||
|
),
|
||||||
|
onYes: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => BottomAlertDialog.multiButton(
|
||||||
|
title: const Text('Starter Pokémon'),
|
||||||
|
body: const Text('Choose a starter Pokémon'),
|
||||||
|
buttons: [
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Turtwig',
|
||||||
|
buttonType: ButtonType.secondary,
|
||||||
|
onPressed: () =>
|
||||||
|
_showDoneDialog(context, 'Turtwig'),
|
||||||
|
),
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Chimchar',
|
||||||
|
buttonType: ButtonType.secondary,
|
||||||
|
onPressed: () =>
|
||||||
|
_showDoneDialog(context, 'Chimchar'),
|
||||||
|
),
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'Piplup',
|
||||||
|
buttonType: ButtonType.secondary,
|
||||||
|
onPressed: () =>
|
||||||
|
_showDoneDialog(context, 'Piplup'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onNo: () => Navigator.pop(context),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showDoneDialog(BuildContext context, String name) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => BottomAlertDialog.icon(
|
||||||
|
title: const Text('Good choice!'),
|
||||||
|
icon: Icon(
|
||||||
|
Icons.catching_pokemon,
|
||||||
|
color: Color(name.hashCode).withAlpha(255),
|
||||||
|
),
|
||||||
|
body: Text('You chose $name to be your starter Pokémon.'),
|
||||||
|
buttons: [
|
||||||
|
const CloseButton(
|
||||||
|
color: Colors.green,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import 'package:example/main.dart';
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||||
// Build our app and trigger a frame.
|
// Build our app and trigger a frame.
|
||||||
await tester.pumpWidget(const MyApp());
|
await tester.pumpWidget(const DialogDemoApp());
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
// Verify that our counter starts at 0.
|
||||||
expect(find.text('0'), findsOneWidget);
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
|
|
@ -8,3 +8,5 @@ export './src/alert_dialogs.dart';
|
||||||
export './src/dialogs.dart';
|
export './src/dialogs.dart';
|
||||||
export './src/popup_parent.dart';
|
export './src/popup_parent.dart';
|
||||||
export './src/popup_service.dart';
|
export './src/popup_service.dart';
|
||||||
|
export './src/bottom_alert_dialog_config.dart';
|
||||||
|
export './src/bottom_alert_dialog.dart';
|
||||||
|
|
299
lib/src/bottom_alert_dialog.dart
Normal file
299
lib/src/bottom_alert_dialog.dart
Normal file
|
@ -0,0 +1,299 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_dialogs/src/bottom_alert_dialog_config.dart';
|
||||||
|
|
||||||
|
class BottomAlertDialogAction extends StatelessWidget {
|
||||||
|
const BottomAlertDialogAction({
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
this.buttonType = ButtonType.tertiary,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
final String text;
|
||||||
|
final ButtonType buttonType;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var config = BottomAlertDialogConfig.of(context);
|
||||||
|
var buttonBuilder = config.buttonBuilder;
|
||||||
|
var translatedText = text;
|
||||||
|
if (text == 'shell.alertdialog.button.yes') {
|
||||||
|
translatedText = config.yesText;
|
||||||
|
} else if (text == 'shell.alertdialog.button.no') {
|
||||||
|
translatedText = config.noText;
|
||||||
|
}
|
||||||
|
return buttonBuilder.call(
|
||||||
|
context,
|
||||||
|
text: translatedText,
|
||||||
|
onPressed: onPressed,
|
||||||
|
buttonType: buttonType,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BottomAlertDialog extends StatelessWidget {
|
||||||
|
factory BottomAlertDialog.custom({
|
||||||
|
required Widget body,
|
||||||
|
required List<Widget> buttons,
|
||||||
|
List<BottomAlertDialogAction>? actions,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog._(
|
||||||
|
closeButton: closeButton,
|
||||||
|
buttons: buttons,
|
||||||
|
actions: actions,
|
||||||
|
body: (_) => body,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory BottomAlertDialog.singleButtonIcon({
|
||||||
|
required Widget title,
|
||||||
|
required Widget body,
|
||||||
|
required Widget icon,
|
||||||
|
required String buttonText,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
ButtonType buttonType = ButtonType.tertiary,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog.icon(
|
||||||
|
closeButton: closeButton,
|
||||||
|
title: title,
|
||||||
|
icon: icon,
|
||||||
|
body: body,
|
||||||
|
buttons: [
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: buttonText,
|
||||||
|
buttonType: buttonType,
|
||||||
|
onPressed: onPressed,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory BottomAlertDialog.yesOrNoIcon({
|
||||||
|
required Widget title,
|
||||||
|
required Widget body,
|
||||||
|
required Widget icon,
|
||||||
|
required VoidCallback onYes,
|
||||||
|
required VoidCallback onNo,
|
||||||
|
bool focusYes = true,
|
||||||
|
bool otherSecondary = false,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog.icon(
|
||||||
|
closeButton: closeButton,
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
icon: icon,
|
||||||
|
buttons: _getYesNoDialogButtons(focusYes, otherSecondary, onYes, onNo),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory BottomAlertDialog.yesOrNo({
|
||||||
|
required Widget title,
|
||||||
|
required Widget body,
|
||||||
|
required VoidCallback onYes,
|
||||||
|
required VoidCallback onNo,
|
||||||
|
bool focusYes = true,
|
||||||
|
bool otherSecondary = false,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog.multiButton(
|
||||||
|
closeButton: closeButton,
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
buttons: const [],
|
||||||
|
actions: _getYesNoDialogButtons(focusYes, otherSecondary, onYes, onNo),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory BottomAlertDialog.icon({
|
||||||
|
required Widget title,
|
||||||
|
required Widget icon,
|
||||||
|
required Widget body,
|
||||||
|
required List<Widget> buttons,
|
||||||
|
List<BottomAlertDialogAction>? actions,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog._(
|
||||||
|
closeButton: closeButton,
|
||||||
|
buttons: buttons,
|
||||||
|
actions: actions,
|
||||||
|
body: (context) => Column(
|
||||||
|
children: [
|
||||||
|
icon,
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: title,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
|
||||||
|
child: body,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory BottomAlertDialog.multiButton({
|
||||||
|
required Widget title,
|
||||||
|
required Widget body,
|
||||||
|
required List<BottomAlertDialogAction> buttons,
|
||||||
|
List<BottomAlertDialogAction>? actions,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog._(
|
||||||
|
closeButton: closeButton,
|
||||||
|
buttons: buttons,
|
||||||
|
actions: actions,
|
||||||
|
body: (context) => Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 20,
|
||||||
|
),
|
||||||
|
child: title,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
|
||||||
|
child: body,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
factory BottomAlertDialog.singleButton({
|
||||||
|
required Widget title,
|
||||||
|
required Widget body,
|
||||||
|
required String buttonText,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
ButtonType buttonType = ButtonType.tertiary,
|
||||||
|
bool? closeButton,
|
||||||
|
}) {
|
||||||
|
return BottomAlertDialog.multiButton(
|
||||||
|
closeButton: closeButton,
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
buttons: [
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: buttonText,
|
||||||
|
onPressed: onPressed,
|
||||||
|
buttonType: buttonType,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const BottomAlertDialog._({
|
||||||
|
required this.buttons,
|
||||||
|
required this.body,
|
||||||
|
this.actions,
|
||||||
|
this.closeButton = false,
|
||||||
|
});
|
||||||
|
final List<Widget> buttons;
|
||||||
|
final WidgetBuilder body;
|
||||||
|
final bool? closeButton;
|
||||||
|
final List<BottomAlertDialogAction>? actions;
|
||||||
|
|
||||||
|
static List<BottomAlertDialogAction> _getYesNoDialogButtons(
|
||||||
|
bool focusYes,
|
||||||
|
bool otherSecondary,
|
||||||
|
VoidCallback onYes,
|
||||||
|
VoidCallback onNo,
|
||||||
|
) {
|
||||||
|
return <BottomAlertDialogAction>[
|
||||||
|
if (focusYes) ...[
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'shell.alertdialog.button.no',
|
||||||
|
buttonType:
|
||||||
|
otherSecondary ? ButtonType.secondary : ButtonType.tertiary,
|
||||||
|
onPressed: onNo,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'shell.alertdialog.button.yes',
|
||||||
|
buttonType: focusYes
|
||||||
|
? ButtonType.primary
|
||||||
|
: otherSecondary
|
||||||
|
? ButtonType.secondary
|
||||||
|
: ButtonType.tertiary,
|
||||||
|
onPressed: onYes,
|
||||||
|
),
|
||||||
|
if (!focusYes) ...[
|
||||||
|
BottomAlertDialogAction(
|
||||||
|
text: 'shell.alertdialog.button.no',
|
||||||
|
buttonType: ButtonType.primary,
|
||||||
|
onPressed: onNo,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var config = BottomAlertDialogConfig.of(context);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
AlertDialog(
|
||||||
|
insetPadding: EdgeInsets.zero,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
backgroundColor:
|
||||||
|
config.backgroundColor ?? Theme.of(context).cardColor,
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(10),
|
||||||
|
topRight: Radius.circular(10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
content: SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
body.call(context),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
top: buttons.isNotEmpty ? 40 : 0,
|
||||||
|
bottom: 20,
|
||||||
|
left: 20,
|
||||||
|
right: 20,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
|
children: (actions == null) ? buttons : actions!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (closeButton ?? false) ...[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.topRight,
|
||||||
|
child: config.closeButtonBuilder.call(
|
||||||
|
context,
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
127
lib/src/bottom_alert_dialog_config.dart
Normal file
127
lib/src/bottom_alert_dialog_config.dart
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
enum ButtonType {
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
tertiary,
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef ButtonBuilder = Widget Function(
|
||||||
|
BuildContext context, {
|
||||||
|
required String text,
|
||||||
|
required void Function() onPressed,
|
||||||
|
ButtonType buttonType,
|
||||||
|
});
|
||||||
|
|
||||||
|
typedef CloseButtonBuilder = Widget Function(
|
||||||
|
BuildContext context, {
|
||||||
|
required void Function() onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
class BottomAlertDialogConfig extends InheritedWidget {
|
||||||
|
const BottomAlertDialogConfig({
|
||||||
|
required super.child,
|
||||||
|
ButtonBuilder? buttonBuilder,
|
||||||
|
CloseButtonBuilder? closeButtonBuilder,
|
||||||
|
this.yesText = 'Yes',
|
||||||
|
this.noText = 'No',
|
||||||
|
this.backgroundColor,
|
||||||
|
super.key,
|
||||||
|
}) : _buttonBuilder = buttonBuilder,
|
||||||
|
_closeButtonBuilder = closeButtonBuilder;
|
||||||
|
|
||||||
|
final ButtonBuilder? _buttonBuilder;
|
||||||
|
final CloseButtonBuilder? _closeButtonBuilder;
|
||||||
|
final String yesText;
|
||||||
|
final String noText;
|
||||||
|
final Color? backgroundColor;
|
||||||
|
|
||||||
|
ButtonBuilder get buttonBuilder =>
|
||||||
|
_buttonBuilder ??
|
||||||
|
(
|
||||||
|
context, {
|
||||||
|
required onPressed,
|
||||||
|
required text,
|
||||||
|
buttonType = ButtonType.tertiary,
|
||||||
|
}) {
|
||||||
|
var theme = Theme.of(context);
|
||||||
|
switch (buttonType) {
|
||||||
|
case ButtonType.primary:
|
||||||
|
return ElevatedButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor:
|
||||||
|
MaterialStateProperty.all(theme.colorScheme.primary),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Colors.black),
|
||||||
|
shape: MaterialStateProperty.all(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
side: BorderSide(color: theme.colorScheme.primary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(text),
|
||||||
|
);
|
||||||
|
case ButtonType.secondary:
|
||||||
|
return ElevatedButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all(Colors.white),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Colors.black),
|
||||||
|
shape: MaterialStateProperty.all(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
side: BorderSide(color: theme.colorScheme.primary),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(text),
|
||||||
|
);
|
||||||
|
case ButtonType.tertiary:
|
||||||
|
return ElevatedButton(
|
||||||
|
style: ButtonStyle(
|
||||||
|
shadowColor: MaterialStateProperty.all(Colors.transparent),
|
||||||
|
backgroundColor: MaterialStateProperty.all(Colors.white),
|
||||||
|
foregroundColor: MaterialStateProperty.all(Colors.black),
|
||||||
|
shape: MaterialStateProperty.all(
|
||||||
|
RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(15),
|
||||||
|
side: const BorderSide(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(text),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CloseButtonBuilder get closeButtonBuilder =>
|
||||||
|
_closeButtonBuilder ??
|
||||||
|
(context, {required onPressed}) {
|
||||||
|
return IconButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.close,
|
||||||
|
size: 25,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
static BottomAlertDialogConfig of(BuildContext context) {
|
||||||
|
var result =
|
||||||
|
context.dependOnInheritedWidgetOfExactType<BottomAlertDialogConfig>();
|
||||||
|
assert(result != null, 'No BottomAlertDialogConfig found in context');
|
||||||
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool updateShouldNotify(BottomAlertDialogConfig oldWidget) =>
|
||||||
|
buttonBuilder != oldWidget.buttonBuilder ||
|
||||||
|
closeButtonBuilder != oldWidget.closeButtonBuilder;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_dialogs
|
name: flutter_dialogs
|
||||||
description: A new Flutter package project.
|
description: A new Flutter package project.
|
||||||
version: 0.0.2
|
version: 1.0.0
|
||||||
homepage: https://github.com/Iconica-Development/flutter_dialogs
|
homepage: https://github.com/Iconica-Development/flutter_dialogs
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
Loading…
Reference in a new issue