Skip to content

Commit e09d593

Browse files
committed
Add showTextInputDialog
1 parent 3c558c7 commit e09d593

File tree

9 files changed

+415
-20
lines changed

9 files changed

+415
-20
lines changed

example/lib/pages/alert_page.dart

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,32 +90,41 @@ class _AlertPageState extends State<AlertPage> {
9090
),
9191
ListTile(
9292
title: const Text('OK/Cancel Dialog (Default: Cancel)'),
93-
onTap: () => showOkCancelAlertDialog(
94-
context: context,
95-
title: 'Title',
96-
message: 'This is message.',
97-
defaultType: OkCancelAlertDefaultType.cancel,
98-
),
93+
onTap: () async {
94+
final result = await showOkCancelAlertDialog(
95+
context: context,
96+
title: 'Title',
97+
message: 'This is message.',
98+
defaultType: OkCancelAlertDefaultType.cancel,
99+
);
100+
logger.info(result);
101+
},
99102
),
100103
ListTile(
101104
title: const Text('OK/Cancel Dialog (Destructive)'),
102-
onTap: () => showOkCancelAlertDialog(
103-
context: context,
104-
title: 'Title',
105-
message: 'This is message.',
106-
isDestructiveAction: true,
107-
),
105+
onTap: () async {
106+
final result = await showOkCancelAlertDialog(
107+
context: context,
108+
title: 'Title',
109+
message: 'This is message.',
110+
isDestructiveAction: true,
111+
);
112+
logger.info(result);
113+
},
108114
),
109115
ListTile(
110116
title: const Text('OK/Cancel Dialog (useActionSheetForCupertino)'),
111-
onTap: () => showOkCancelAlertDialog(
112-
context: context,
113-
title: 'Title',
114-
message: 'This is message.',
115-
isDestructiveAction: true,
116-
cancelLabel: 'No!',
117-
useActionSheetForCupertino: true,
118-
),
117+
onTap: () async {
118+
final result = await showOkCancelAlertDialog(
119+
context: context,
120+
title: 'Title',
121+
message: 'This is message.',
122+
isDestructiveAction: true,
123+
cancelLabel: 'No!',
124+
useActionSheetForCupertino: true,
125+
);
126+
logger.info(result);
127+
},
119128
),
120129
],
121130
),
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import 'package:adaptive_dialog/adaptive_dialog.dart';
2+
import 'package:example/router.dart';
3+
import 'package:example/util/util.dart';
4+
import 'package:flutter/material.dart';
5+
6+
class TextInputDialogPage extends StatelessWidget {
7+
const TextInputDialogPage({Key key}) : super(key: key);
8+
9+
static const routeName = '/text_input_dialog';
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
return Scaffold(
14+
appBar: AppBar(
15+
title: Text(pascalCaseFromRouteName(routeName)),
16+
),
17+
body: ListView(
18+
children: <Widget>[
19+
ListTile(
20+
title: const Text('No Title/Message'),
21+
onTap: () async {
22+
final text = await showTextInputDialog(
23+
context: context,
24+
textFields: const [
25+
DialogTextField(),
26+
],
27+
);
28+
logger.info(text);
29+
},
30+
),
31+
ListTile(
32+
title: const Text('No Message'),
33+
onTap: () async {
34+
final text = await showTextInputDialog(
35+
context: context,
36+
textFields: const [
37+
DialogTextField(),
38+
],
39+
titleLabel: 'Hello',
40+
);
41+
logger.info(text);
42+
},
43+
),
44+
ListTile(
45+
title: const Text('Title/Message'),
46+
onTap: () async {
47+
final text = await showTextInputDialog(
48+
context: context,
49+
textFields: const [
50+
DialogTextField(),
51+
],
52+
titleLabel: 'Hello',
53+
messageLabel: 'This is a message',
54+
);
55+
logger.info(text);
56+
},
57+
),
58+
ListTile(
59+
title: const Text('Multi Text Field'),
60+
onTap: () async {
61+
final text = await showTextInputDialog(
62+
context: context,
63+
textFields: const [
64+
DialogTextField(
65+
hintText: 'Email',
66+
initialText: '[email protected]',
67+
),
68+
DialogTextField(
69+
hintText: 'Password',
70+
obscureText: true,
71+
),
72+
],
73+
titleLabel: 'Hello',
74+
messageLabel: 'This is a message',
75+
);
76+
logger.info(text);
77+
},
78+
),
79+
],
80+
),
81+
);
82+
}
83+
}

example/lib/router.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'package:example/pages/text_input_dialog_page.dart';
12
import 'package:flutter/material.dart';
23
import 'package:recase/recase.dart';
34

@@ -8,6 +9,7 @@ class Router {
89
final Map<String, WidgetBuilder> pushRoutes = {
910
AlertPage.routeName: (context) => const AlertPage(),
1011
SheetPage.routeName: (context) => const SheetPage(),
12+
TextInputDialogPage.routeName: (context) => const TextInputDialogPage(),
1113
};
1214

1315
Route onGenerateRoute(RouteSettings settings) {
@@ -39,5 +41,6 @@ class PageInfo {
3941
static List<PageInfo> get all => [
4042
AlertPage.routeName,
4143
SheetPage.routeName,
44+
TextInputDialogPage.routeName,
4245
].map((rn) => PageInfo(routeName: rn)).toList();
4346
}

lib/adaptive_dialog.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export 'src/adaptive_style.dart';
22
export 'src/alert_dialog/alert_dialog.dart';
33
export 'src/modal_action_sheet/modal_action_sheet.dart';
4+
export 'src/text_input_dialog/text_input_dialog.dart';

lib/src/extensions/extensions.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export 'list.dart';
12
export 'string.dart';
23
export 'theme_data.dart';

lib/src/extensions/list.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extension ListWithIndex<T, E> on List<T> {
2+
List<E> mapWithIndex<E>(E Function(T item, int index) function) {
3+
final list = <E>[];
4+
asMap().forEach((index, element) {
5+
list.add(function(element, index));
6+
});
7+
return list;
8+
}
9+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import 'package:adaptive_dialog/adaptive_dialog.dart';
2+
import 'package:flutter/cupertino.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:adaptive_dialog/src/extensions/extensions.dart';
5+
6+
class CupertinoTextInputDialog extends StatefulWidget {
7+
const CupertinoTextInputDialog({
8+
@required this.textFields,
9+
this.titleLabel,
10+
this.okLabel,
11+
this.cancelLabel,
12+
this.messageLabel,
13+
this.style = AdaptiveStyle.adaptive,
14+
});
15+
@override
16+
_CupertinoTextInputDialogState createState() =>
17+
_CupertinoTextInputDialogState();
18+
19+
final List<DialogTextField> textFields;
20+
final String titleLabel;
21+
final String okLabel;
22+
final String cancelLabel;
23+
final String messageLabel;
24+
final AdaptiveStyle style;
25+
}
26+
27+
class _CupertinoTextInputDialogState extends State<CupertinoTextInputDialog> {
28+
List<TextEditingController> _textControllers;
29+
30+
@override
31+
void initState() {
32+
super.initState();
33+
34+
_textControllers = widget.textFields
35+
.map((tf) => TextEditingController(text: tf.initialText))
36+
.toList();
37+
}
38+
39+
@override
40+
void dispose() {
41+
for (final c in _textControllers) {
42+
c.dispose();
43+
}
44+
super.dispose();
45+
}
46+
47+
@override
48+
Widget build(BuildContext context) {
49+
final navigator = Navigator.of(context);
50+
void pop() => navigator.pop(
51+
_textControllers.map((c) => c.text).toList(),
52+
);
53+
void cancel() => navigator.pop();
54+
final titleText =
55+
widget.titleLabel == null ? null : Text(widget.titleLabel);
56+
final okText = Text(
57+
widget.okLabel ?? MaterialLocalizations.of(context).okButtonLabel,
58+
);
59+
BoxDecoration borderDecoration({
60+
@required bool isTopRounded,
61+
@required bool isBottomRounded,
62+
}) {
63+
const radius = 6.0;
64+
const borderSide = BorderSide(
65+
color: CupertinoDynamicColor.withBrightness(
66+
color: Color(0x33000000),
67+
darkColor: Color(0x33FFFFFF),
68+
),
69+
style: BorderStyle.solid,
70+
width: 0,
71+
);
72+
return BoxDecoration(
73+
color: const CupertinoDynamicColor.withBrightness(
74+
color: CupertinoColors.white,
75+
darkColor: CupertinoColors.black,
76+
),
77+
border: const Border(
78+
top: borderSide,
79+
bottom: borderSide,
80+
left: borderSide,
81+
right: borderSide,
82+
),
83+
borderRadius: BorderRadius.vertical(
84+
top: Radius.circular(isTopRounded ? radius : 0),
85+
bottom: Radius.circular(isBottomRounded ? radius : 0),
86+
),
87+
);
88+
}
89+
90+
return CupertinoAlertDialog(
91+
title: titleText,
92+
content: Column(
93+
mainAxisSize: MainAxisSize.min,
94+
children: <Widget>[
95+
if (widget.messageLabel != null) Text(widget.messageLabel),
96+
const SizedBox(height: 22),
97+
..._textControllers.mapWithIndex(
98+
(c, i) {
99+
final field = widget.textFields[i];
100+
return CupertinoTextField(
101+
controller: c,
102+
autofocus: i == 0,
103+
placeholder: field.hintText,
104+
obscureText: field.obscureText,
105+
decoration: borderDecoration(
106+
isTopRounded: i == 0,
107+
isBottomRounded: i == _textControllers.length - 1,
108+
),
109+
);
110+
},
111+
),
112+
],
113+
),
114+
actions: <Widget>[
115+
CupertinoDialogAction(
116+
child: Text(
117+
widget.cancelLabel ??
118+
MaterialLocalizations.of(context)
119+
.cancelButtonLabel
120+
.capitalizedForce,
121+
),
122+
onPressed: cancel,
123+
isDefaultAction: true,
124+
),
125+
CupertinoDialogAction(
126+
child: okText,
127+
onPressed: pop,
128+
),
129+
],
130+
);
131+
}
132+
}

0 commit comments

Comments
 (0)