AlertDialog content isn't showing any text - flutter

I have an AlertDialog that I want to have hyperlinks within the text. This is what I have currently:
await showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) => AgreementDialog());
// AgreementDialog.dart
build(BuildContext context) {
return StreamBuilder(
stream: agreementBloc.agreements,
builder:
(BuildContext context, AsyncSnapshot<AgreementDocuments> snapshot) {
if (snapshot.hasError) {
SnackBars.errorSnackBar(context, snapshot.error.toString());
return Spinner();
}
if (!snapshot.hasData) {
return Spinner();
}
return AlertDialog(
title: Text('Wait'),
content: Text('test tes test'),
actions: <Widget>[
TextButton(
child: Text('Approve'),
onPressed: () => Navigator.of(context).pop()),
],
);
});
}
The above works and will render 'test tes test', but now when I try to use the solution here I can't see the content text at all. Here is what I've tried:
return AlertDialog(
title: Text('One second...'),
content: RichText(
text: TextSpan(children: [
TextSpan(text: 'By clicking Agree, I hereby agree to the '),
TextSpan(text: 'Blah blah blah'),
]),
),
actions: <Widget>[
TextButton(
child: Text('Approve'),
onPressed: () => Navigator.of(context).pop()),
],
);
but it ends up blank:
Does anyone know what I'm doing wrong?

This is gonna be really dumb but I also don't know why my app was doing this...
The color was white so it blended in. I have to set my TextSpan to a color other than white.
🙃

Related

How to enable/disable dialog buttons (actions)

I have a helper function to create dialogs in my flutter app:
Future<void> showContentDialog(BuildContext context,
{required Widget content, String? title, List<Tuple2<String, void Function()>>? actions}) async {
Widget? titleWidget;
if (title != null) {
titleWidget = Text(
title,
style: Theme.of(context).textTheme.titleSmall!.copyWith(fontWeight: FontWeight.bold),
);
}
var dialogActions = <Widget>[];
if (actions != null) {
dialogActions.addAll(
actions.map(
(a) => TextButton(
child: Text(a.item1),
onPressed: () {
a.item2();
}),
),
);
}
await showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
title: titleWidget,
content: SizedBox(width: ThemeHelpers.maxPopupWidth, child: content),
actions: dialogActions,
),
);
}
There is another similar one that is used on Apple devices that uses equivalent widgets.
I can easyly manage state on the content portion of the dialog by wrapping it in a StatefulBuilder, but how can I enable and disable the dialog buttons (the actions passed to the AlertDialog) builder depending on content state?
My first idea was to add another a ValueNotifier parameter to the action builders and wrap them in ValueListenerBuilders but that didn't work.
Do I have any way of doing that other than including the actions as buttons inside the content (were I can easyly manage their state)?
You can pass null on onPressed to disable the button state. While it is not clear from where you like to controll the state, you can use ValueNotifier, and it work for all widget
final ValueNotifier<bool> enableButton = ValueNotifier(false);
Future<void> showContentDialog(
BuildContext context,
) async {
await showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
content: SizedBox(
width: 222,
child: Column(
children: [
Text("A"),
ElevatedButton(
onPressed: () {
enableButton.value = !enableButton.value;
},
child: Text("toggleButtonState"),
)
],
),
),
actions: [
ValueListenableBuilder<bool>(
valueListenable: enableButton,
builder: (context, value, child) => ElevatedButton(
onPressed: value ? () {} : null,
child: Text("BTN"),
),
),
],
),
);
}
In content add column and add dialog widgets in it
await showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
title: titleWidget,
content: Column(
mainAxisSize: MainAxisSize.min,
children : [
SizedBox(width: ThemeHelpers.maxPopupWidth, child: content),
dialogActions,
]
)
),
);

How to make Alert Dialog working in flutter

I am using below code to register the user, there is an option to upload image , if it is null the user won't be registered, that is working accurately, only thing I am facing is that if the image is null it should the alert dialog to the user , but the alert dialog is not working at all.
How should I implement the alert dialog?
if (avatarImageFile != null ) {
FirebaseAuth.instance
.createUserWithEmailAndPassword(
email: emailInputController.text,
password: pwdInputController.text)
.then((currentUser) =>
Firestore.instance
.collection("users")
.document(currentUser.user.uid)
.setData({
"username": userNameInputController.text,
"email": emailInputController.text,
})
.then((result) =>
{
uploadFile(currentUser.user.uid),
print(currentUser.user.getIdToken()),
currentUser.user.sendEmailVerification(),
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) =>
MainScreen(
)),
(_) => false),
})
.catchError((err) => print(err)))
.catchError((err) => print(err));
}
else {
print("Please Upload the Image");
AlertDialog(
title: Text("Image Required"),
content: Text("Please upload the image"),
actions: <Widget>[
FlatButton(
child: Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
You need to use the function showDialog so the dialog appears:
else {
print("Please Upload the Image");
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Image Required"),
content: Text("Please upload the image"),
actions: <Widget>[
FlatButton(
child: Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
};
);
}
Peter Haddad's answer solves the problem but I would suggest placing the AlertDialog in a widget so that it would be easy to reuse the AlertDialog again. Here is how I did it for my project:
Dialogs.dart:
import 'package:flutter/material.dart';
enum alertDialogAction { cancel, save }
class Dialogs {
static Future<alertDialogAction> alertDialog(
BuildContext context,
String title,
String body,
String cancel,
String save,
) {
Future<alertDialogAction> action = showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
title: Text(title),
content: Text(body),
actions: <Widget>[
FlatButton(
onPressed: () =>
Navigator.pop(context, alertDialogAction.cancel),
child: Text(cancel)),
RaisedButton(
color: Colors.orange,
onPressed: () =>
Navigator.of(context).pop(alertDialogAction.save),
child: Text(
save,
style: TextStyle(color: Colors.white),
)),
],
);
});
return (action != null) ? action : alertDialogAction.cancel;
}
Here is how you can call it:
onPressed:() async {
final action= await Dialogs.alertDialog(context,"Title","Body","Cancel","Save");
//cancel and save are the button text for cancel and save operation
if(action==alertDialogAction.save){
//do something
Navigator.pop(context);
}
}
You can also show a dialog box using scaffold, for example,
Scaffold.of(context).showSnackBar(SnackBar(content: AlertDialog(content: Text('Alert!!!'))));
But you have to keep in mind that context should be of the current scaffold.
So you might want to wrap the body property (in Scaffold) in a Builder Widget and then when you use context inside that builder widget, that context will be of current scaffold.
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Your Title!!!"),
content: Text("Your Content!!!"),
actions: <Widget>[
FlatButton(
child: Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
};
);

How to disable onBackPressed() for AlertDialog flutter

I've got an AlertDialog() that it's barrierDismissible has been set to false. But yet when user presses the back button on android device the AlertDialog closes. How can I compeletly prevent the user from closing the AlertDialog()?
Here's what I've done so far:
return showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Title'),
content: Text('This is the alert dialog content'),
actions: <Widget>[
FlatButton(
child: Text('ok'),
onPressed: () {
Navigator.of(context).pop();
print('ok you win');
},
),
],
);
},
);
Try this way use WillPopScope() to handle onBackPressed() event
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return WillPopScope(
onWillPop: () {return Future.value(false);},
child: return AlertDialog(
title: Text('Title'),
content: Text('This is the alert dialog content'),
actions: <Widget>[
FlatButton(
child: Text('ok'),
onPressed: () {
Navigator.of(context).pop();
print('ok you win');
},
),
],
),
);
});
You can use the WillPopScope as a parent of the AlertDialog
showDialog(context: context,builder: (BuildContext context)
{
return WillPopScope(
onWillPop: () async =>false,
child: AlertDialog(
title: Text('Title'),
content: Text('Sample'),
actions: <Widget>[
FlatButton(
child: Text('ok'),
onPressed: (){
Navigator.of(context).pop();
},
)
],
),
);

Alert Dialog on onTap on ListTile

How can I create a AlertDialog by clicking/tapping on ListTile.
Currently I'm doing this and nothing happens when it's clicked.
body: ListView(
children: <Widget>[
ListTile(
title: Text('Theme'),
onTap: (){
AlertDialog(
title: Text('Hi'),
);
},
)
],
),
PS: I'm a noob, please go easy on me.
you are very close, you created the dialog, just need to show it:
body: ListView(
children: <Widget>[
ListTile(
title: Text('Theme'),
onTap: () {
AlertDialog alert = AlertDialog(
title: Text('Hi'),
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
},
)
],
),
Change your ListTile with this.
ListTile(
title: Text('Theme'),
onTap: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Alert Dialog Example'),
content: Text('Alert Dialog Body Goes Here ..'),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('OK')),
],
);
});
},
)
I have also added some properties to use the AlertDialog(), like title, content and actions

How to make dialog scrollable?

I'm developing a Flutter App and in this app, there are some Dialogs. In these dialogs, there is only a Text; but when the text is too long, I can't scroll the text.
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
title: Text(title),
content: Text(description),
actions: < Widget > [
FlatButton(
child: Text("PLAY"),
onPressed: () {
_launchURL(link);
},
)
],
)
);
You can use ListBody inside SingleChildScrollView for this use case.
Here you go:
showDialog(
context: context,
barrierDismissible: true,
builder: (context) => AlertDialog(
title: Text(title),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text(description)
],
),
),
actions: < Widget > [
FlatButton(
child: Text("PLAY"),
onPressed: () {
_launchURL(link);
},
)
],
)
);