flutter version 2.5.2 기준으로 작성됨
dialog
를 호출한 위젯의 상태도 바꾸고 싶은 경우와 아닌 경우를 나눠서 설명dialog
내부의 상태만 변경하고 싶을 때The widget returned by the builder does not share a context with the location that showDialog is originally called from. Use a StatefulBuilder or a custom StatefulWidget if the dialog needs to update dynamically.
showDialog 문서에서는 호출한 곳의 context를 공유하지 않으니, Dialog
를 동적으로 변경하고 싶으면 StatefulBuilder
나 StatefulWidget
으로 사용하라고 적혀있음
StatefulBuilder
사용Dialog
에서 상태 변경을 원하는 위젯을 StatefulBuilder
로 감싸서 사용Future<dynamic> showStatefulBuilderDialog(BuildContext context) async {
await showDialog<void>(
context: context,
builder: (_) {
int? selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (__, StateSetter setState) {
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(3, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setState(() => selectedRadio = value);
},
);
}),
);
},
),
);
},
);
}
StatefulWidget
사용Dialog
를 StatefulWidget
으로 커스텀해서 사용함// dialog를 사용하는 곳
Future<dynamic> showStatefulWidgetDialog(BuildContext context) async {
await showDialog<void>(
context: context,
builder: (_) {
return MyStatefulDialog();
},
);
}
// StatefulWidget으로 dialog 작성
class MyStatefulDialog extends StatefulWidget {
State<MyStatefulDialog> createState() => _MyStatefulDialogState();
}
class _MyStatefulDialogState extends State<MyStatefulDialog> {
int? selectedRadio = 0;
Widget build(BuildContext context) {
return AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(3, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setState(() => selectedRadio = value);
},
);
}),
),
);
}
}
Dialog
를 호출한 위젯에도 Dialog
의 변경 값을 바로바로 표시하고 싶을 때Dialog
를StatefulWidget
으로 분리하여 구현한 경우는 잘 작동하므로 제외하겠음StatefulBuilder
사용StatefulWidget
에서 StatefulBuilder
를 사용한 경우 이미 setState()
가 존재하므로 StatefulBuilder
의 StateSetter
의 메서드명을setState
로 선언하면 이름이 중복되는 문제가 발생한다Builder
안의 StateSetter setState
가 호출되므로 원하던 바깥 위젯의 상태는 변경되지 않는다 (context share 안함)설명을 위해 코드를 짧게 한 스샷이며,
setState
의 주인은 각각 색깔로 매칭함
StateSetter
의 setState
를 다른 이름으로 선언해주면 잘 동작한다Future<dynamic> showStatefulDialog() async {
await showDialog<void>(
context: context,
builder: (_) {
int? selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (__, StateSetter setDialogState) { // 변수명 변경
return Column(
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(3, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int? value) {
setDialogState(() => selectedRadio = value);
setState(() => text = 'MyStatefulWidget $value');
},
);
}),
);
},
),
);
},
);
}