티스토리 뷰

플러터에서 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"),
            );
          }),
        ),
      ),
    );
  }
}

 

댓글
공지사항