I have made a dialog appear which can be closed if someone correctly types in a certain word. I wanted to know if it was possible to make a second dialog appear if someone does not type anything into the first text box within a certain timeframe. For example, if the person does not input text within the next 5 minutes, is there any way to trigger a second dialog to show up?
Future.delayed(Duration(seconds: 5), () {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: Text('Your time finished'),
content: Text('Type "OKAY" if you want to go back to the homepage'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: TextFormField(
controller: _textEditingController,
validator: (String? word){
if (word != OKAY){
_NoDialog();
}
else{
Navigator.pop(context);
}
},
),
),
],
);
});
});
I called the function NoDialog
if the text the person gives is incorrect, but I am not sure how to make an 'if' statement if the person does not put anything in the text box for a certain period of time.
I think I could do an 'if' statement if the person leaves the text blank and then call a new function with a Future.delayed attached, but I couldnt find a way to make an 'if' statement for the case when no text is entered. Also in this case, I believe the person would have to hit the 'enter' key, but I want the second dialog to show up because the user has not touched anything on the screen. Is this possible?
CodePudding user response:
In simple case, you can show nested-overlap dialog with passing same the build-context.
The First dialog will be
_userInputCheckerDialog({
required BuildContext context,
required String correctText,
Duration maxTime = const Duration(seconds: 2),
}) async {
bool _noInteraction = true;
/// apear if user doesnt type anything within
Future.delayed(maxTime).then((t) async {
if (_noInteraction) await _showSecondDialog(context);
});
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return StatefulBuilder(
///may need in future to change variable inside dialog
builder: (context, setStateSB) {
return AlertDialog(
content: TextField(
onChanged: (value) async {
_noInteraction = false;
if (value == correctText) {
Navigator.of(context)
.pop(); // close after getting currect text
}
},
),
);
},
);
},
);
}
Then the inner dialog is having the same context
_showSecondDialog(BuildContext context) async {
await showDialog(
context: context,
builder: (context) => const AlertDialog(
content: Text("Hey start typing"),
),
);
}
this is only checking 1st time of user interaction.
If you want to use timeframe, we need to use async package to cancel (not really cancelling) the future. You might feel it a little more complicated than the 1st one.
Use async
_showSecondDialog(BuildContext context) async {
await showDialog(
context: context,
builder: (context) => const AlertDialog(
content: Text("Hey start typing"),
),
);
}
CancelableOperation _restartTimer({
CancelableOperation? cancelableOperation,
Duration duration = const Duration(seconds: 4),
required BuildContext context,
}) {
if (cancelableOperation != null) {
cancelableOperation.cancel();
cancelableOperation = null;
}
cancelableOperation = CancelableOperation.fromFuture(
Future.delayed(
duration,
),
).then((p0) async {
await _showSecondDialog(context);
});
return cancelableOperation;
}
_userInputCheckerDialog({
required BuildContext context,
required String correctText,
Duration maxTime = const Duration(seconds: 2),
}) async {
CancelableOperation? _cancelableOperation;
///start timer at startUp
_cancelableOperation = _restartTimer(
context: context,
cancelableOperation: _cancelableOperation,
duration: maxTime,
);
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return StatefulBuilder(
///may need in future to change variable inside dialog
builder: (context, setStateSB) {
return AlertDialog(
content: TextField(
onChanged: (value) async {
_cancelableOperation = _restartTimer(
context: context,
cancelableOperation: _cancelableOperation);
if (value == correctText) {
_cancelableOperation!.cancel();
Navigator.of(context)
.pop(); // close after getting currect text
}
},
),
);
},
);
},
);
}