06.06.2024 в 20:42
Полина Родионова
Как добавить функциональность состояний внутрь функции showDialog() во Flutter
Когда я добавляю виджет CheckBox() в содержимое виджета AlertDialog внутри функции showDialog() в функции TextButton виджета onPressed(), я обнаруживаю, что флажок не перестраивается, когда я нажимаю на него.
Флажок не перестраивался, потому что функция showDialog() имеет свой собственный контекст сборки. Даже когда я использую StatefulWidget, флажок не реагирует и не перестраивается, как ожидалось, когда я нажимаю на него.
Поэтому я обернул виджет AlertDialog с помощью виджета StatefulBuilder и переместил булеву переменную для значения флажка выше него, и это решило проблему с флажком.
Прежде:
import 'package:flutter/material.dart';
import '../../constants/colors.dart';
import '../../constants/styles.dart';
class DialogSendFeedback extends StatefulWidget {
const DialogSendFeedback({super.key});
@override
State<DialogSendFeedback> createState() => _DialogSendFeedbackState();
}
class _DialogSendFeedbackState extends State<DialogSendFeedback> {
final TextEditingController feedback = TextEditingController();
final FocusNode feedbackFocus = FocusNode();
bool agree = false;
@override
void dispose() {
feedback.dispose();
feedbackFocus.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextButton.icon(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Send the project to Engineers'),
content: SizedBox(
width: 600,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Row(
children: [
Expanded(
child: Text(
'We are sorry that you encountered some issues. To assist us in investigating the matter, kindly provide the details of the project.',
maxLines: 3,
))
],
),
const SizedBox(
height: 16,
),
Expanded(
child: Row(
children: [
Expanded(
child: TextFormField(
controller: feedback,
focusNode: feedbackFocus,
autofocus: true,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
maxLines: 100,
decoration: const InputDecoration(
alignLabelWithHint: true,
contentPadding: EdgeInsets.all(8),
label: Text('Issue detail'),
hintText:
'Describe the issue as detailed as possible.'),
))
],
),
),
const SizedBox(
height: 16,
),
Row(
children: [
Checkbox(
checkColor: whiteColor,
fillColor: WidgetStateProperty.resolveWith(
(states) => darkTealColor),
value: agree,
onChanged: (bool? value) {
setState(() {
agree = value!;
});
}),
const SizedBox(
width: 8,
),
const Expanded(
child: Text(
'I agree to send these project details to Schletter Engineering for their investigation.',
maxLines: 3,
),
)
],
)
],
),
),
actions: [
TextButton(
style: defaultPrimaryButtonStyle,
onPressed: () {
Navigator.of(context).pop(false);
},
child: const Text(
'Do not send',
style: buttonTextWhite,
)),
TextButton(
style: defaultSecondaryButtonStyle,
onPressed: agree == true
? () {
Navigator.of(context).pop(true);
}
: null,
child: Text(
'Send',
style: defaultSecondaryButtonTextStyle,
))
],
);
},
).then((value) {
if (value == true) {
// make a call to backend API to save the feedback
}
});
},
icon: const Icon(
Icons.help_outline_rounded,
color: whiteColor,
),
label: Text(
'Ask for help',
style: defaultPrimaryButtonTextStyle,
));
}
}
После:
import 'package:flutter/material.dart';
import '../../constants/colors.dart';
import '../../constants/styles.dart';
class DialogSendFeedback extends StatefulWidget {
const DialogSendFeedback({super.key});
@override
State<DialogSendFeedback> createState() => _DialogSendFeedbackState();
}
class _DialogSendFeedbackState extends State<DialogSendFeedback> {
final TextEditingController feedback = TextEditingController();
final FocusNode feedbackFocus = FocusNode();
@override
void dispose() {
feedback.dispose();
feedbackFocus.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return TextButton.icon(
onPressed: () {
showDialog(
context: context,
builder: (context) {
bool agree = false; // <- here
return StatefulBuilder( // <- here
builder: (context, setState) => AlertDialog(
title: const Text('Send the project to Engineers'),
content: SizedBox(
width: 600,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Row(
children: [
Expanded(
child: Text(
'We are sorry that you encountered some issues. To assist us in investigating the matter, kindly provide the details of the project.',
maxLines: 3,
))
],
),
const SizedBox(
height: 16,
),
Expanded(
child: Row(
children: [
Expanded(
child: TextFormField(
controller: feedback,
focusNode: feedbackFocus,
autofocus: true,
keyboardType: TextInputType.multiline,
textInputAction: TextInputAction.newline,
maxLines: 100,
decoration: const InputDecoration(
alignLabelWithHint: true,
contentPadding: EdgeInsets.all(8),
label: Text('Issue detail'),
hintText:
'Describe the issue as detailed as possible.'),
))
],
),
),
const SizedBox(
height: 16,
),
Row(
children: [
Checkbox(
checkColor: whiteColor,
fillColor: WidgetStateProperty.resolveWith(
(states) => darkTealColor),
value: agree,
onChanged: (bool? value) {
setState(() {
agree = value!;
});
}),
const SizedBox(
width: 8,
),
const Expanded(
child: Text(
'I agree to send these project details to Schletter Engineering for their investigation.',
maxLines: 3,
),
)
],
)
],
),
),
actions: [
TextButton(
style: defaultPrimaryButtonStyle,
onPressed: () {
Navigator.of(context).pop(false);
},
child: const Text(
'Do not send',
style: buttonTextWhite,
)),
TextButton(
style: defaultSecondaryButtonStyle,
onPressed: agree == true
? () {
Navigator.of(context).pop(true);
}
: null,
child: Text(
'Send',
style: defaultSecondaryButtonTextStyle,
))
],
),
);
},
).then((value) {
if (value == true) {
// make a call to backend API to save the feedback
}
});
},
icon: const Icon(
Icons.help_outline_rounded,
color: whiteColor,
),
label: Text(
'Ask for help',
style: defaultPrimaryButtonTextStyle,
));
}
}
Вот и всё. Надеюсь, вы нашли этот пост полезным.
Счастливого кодинга!