티스토리 뷰
플러터에서 showDialog()를 사용하는 코드를 작성하였다.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("MyApp")),
body: Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Title"),
content: const Text("Hello"),
actions: [
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text("Bye"),
)
],
);
}
);
},
child: const Text("Show Dialog"),
),
),
),
);
}
}
그러나 아래와 같이 에러가 발생한다.
The following assertion was thrown while handling a gesture:
No MaterialLocalizations found.
MyApp widgets require MaterialLocalizations to be provided by a Localizations widget ancestor.
The material library uses Localizations to generate messages, labels, and abbreviations.
To introduce a MaterialLocalizations, either use a MaterialApp at the root of your application to include them automatically, or add a Localization widget with a MaterialLocalizations delegate.
The specific widget that could not find a MaterialLocalizations ancestor was: MyApp
The ancestors of this widget were:
: [root]
renderObject: RenderView#8803a
에러가 발생한 이유
에러 내용을 해석해 보면 MyApp 위젯에 MaterialLocalizations이 없기 때문이라고 한다. MaterialLocalization은 머터리얼 라이브러리에서 메시지, 레이블 등을 생성하는 데 사용한다.
MaterialLocalization은 MaterialApp에서 제공한다. 그러면 MaterialApp의 하위 위젯은 Build시 context를 통해서 Materialization에 접근할 수 있게 된다. 하지만 현재 코드는 MyApp의 context를 사용해서 MaterialApp도 만들고, showDialog도 만들다. 그래서 showDialog은 MaterialLocalization이 필요한데, MyApp의 context에는 MaterialLocalization이 없기 때문에 에러가 발생하는 것이다.
해결 방법
이를 해결하기 위해서는 showDialog에 MaterialLocalization가 포함된 콘텍스트를 전달해야 한다.
1. MaterialApp과 showDialog를 서로 다른 위젯으로 분리한다.
다음 코드는 showDialog에 MaterialLocalization을 전달할 수 있도록 MaterialApp을 main()으로 옮긴 코드가 된다. 이렇게 되면 이제 MyApp의 콘텍스트에서 MaterialLocalization를 얻을 수 있게 된다.
import 'package:flutter/material.dart';
void main() {
runApp(const MaterialApp(home: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("MyApp")),
body: Center(
child: ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Title"),
content: const Text("Hello"),
actions: [
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text("Bye"),
)
],
);
});
},
child: const Text("Show Dialog"),
),
),
);
}
}
2. Builder를 이용해서 새로운 콘텍스트 전달하기
MyApp 위젯의 구조를 그대로 사용하고 싶다면, Builder로 새로운 콘텍스트를 만들어서 showDialog에 전달하는 방법도 있다.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("MyApp")),
body: Center(
child: Builder(builder: (context) {
return ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Title"),
content: const Text("Hello"),
actions: [
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text("Bye"),
)
],
);
},
);
},
child: const Text("Show Dialog"),
);
}),
),
),
);
}
}
'Flutter' 카테고리의 다른 글
플러터] 불변 타입과 가변 타입, 얕은 복사와 깊은 복사 (0) | 2023.07.14 |
---|---|
플러터] State 클래스에서 build 지역 변수 대신 클래스 속성 사용하기 (0) | 2023.07.12 |
플러터] 내비게이터 백 버튼 제어하기 (0) | 2023.07.08 |
플러터] Navigator.push와 MaterialApp의 관계 그리고context (0) | 2023.07.08 |
플러터 프로젝트 생성하고 시뮬레이터 실행하기 (0) | 2023.01.14 |