【问题标题】:Flutter Error: MediaQuery.of() called with a context that does not contain a MediaQueryFlutter 错误:使用不包含 MediaQuery 的上下文调用 MediaQuery.of()
【发布时间】:2020-12-16 22:58:27
【问题描述】:

我一直试图在 Flutter 中获取整个上下文视图的大小。但每次我尝试我都会收到上述错误。 这是我的代码:

import 'package:flutter/material.dart';

void main => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    final size = MediaQuery.of(context).size;
    return new MaterialApp(
      home: new Scaffold(),
    );
  }
}

注意:我也尝试使用StatefulWidget。 请帮我找出我做错了什么。

【问题讨论】:

  • 如何显示页面?
  • void main() => runApp(new MyIntroductionPage());
  • 你能显示确切的错误吗? PS:不要保持最终尺寸,因为当你旋转手机时它可能会改变。
  • @ArnoldParge 标题本身给出了确切的错误。

标签: dart flutter


【解决方案1】:

您的小部件周围需要一个MaterialAppWidgetsApp。他们提供MediaQuery。当您调用.of(context) 时,flutter 将始终查找小部件树以找到小部件。

你通常在 main.dart 中有这个:

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Title',
      theme: kThemeData,
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;

    return Container(
      child: ...,
    );
  }
}

【讨论】:

  • 我刚刚看到您的编辑。调用 MediaQuery.of(context) 时,MaterialApp 必须已经在小部件三中。
  • 我遇到了同样的问题,但在第一次运行时我遇到了这个错误,第二次运行和更多正常工作。
  • 遇到了与@MohammadMeshkani 提到的相同的问题,第二次运行时错误消失
  • 我还是有这个问题。
【解决方案2】:

当您在MaterialApp 中时,您可以访问MediaQuery。您访问媒体查询的位置不正确。

请参考以下代码:

import 'package:flutter/material.dart';

class CommonThings {
  static Size size;
}

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'MediaQuery Demo',
      theme: new ThemeData(
        primarySwatch: Colors.red,
      ),
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    CommonThings.size = MediaQuery.of(context).size;
    print('Width of the screen: ${CommonThings.size.width}');
    return new Container();
  }
}

我特意创建了一个类CommonThings,它具有静态大小,以便您可以在整个应用程序中使用它。

【讨论】:

    【解决方案3】:

    我使用以下方法修复了它。首先,我创建了一个名为MyWidget 的新类,并在MaterialApphome: 内将其返回到MyApp。参考以下代码:

    import 'package:flutter/material.dart';
    
    void main => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
    
        return new MaterialApp(
          home: new MyWidget(),
        );
      }
    } 
    
    class MyWidget extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
    
        final size = MediaQuery.of(context).size;
        return new MaterialApp(
          home: new Scaffold(),
        );
      }
    } 
    

    另外,将 size 声明为 final 并不重要。处理方向/旋转。

    【讨论】:

    • 多么奇怪的行为。改为使用 WidgetsBinding.instance.window.physicalSize
    【解决方案4】:

    对我们有用的是使用 WidgetsBinding.instance.window 而不是 MediaQuery - 在设置 MaterialApp 的主题时也是如此:

    _pixelRatio = WidgetsBinding.instance.window.devicePixelRatio;
    _screenWidth = WidgetsBinding.instance.window.physicalSize.width;
    _screenHeight = WidgetsBinding.instance.window.physicalSize.height;
    _statusBarHeight = WidgetsBinding.instance.window.padding.top;
    _bottomBarHeight = WidgetsBinding.instance.window.padding.bottom;
    _textScaleFactor = WidgetsBinding.instance.window.textScaleFactor;
    

    【讨论】:

    • WidgetsBinding.instance.window.padding.topMediaQuery.of(context).padding.top; 的两个不同结果
    • @BloodLoss 你可以改用WidgetsBinding.instance.window.viewPadding
    • MediaQueryData.fromWindow(WidgetsBinding.instance.window) 为您返回与MediaQuery.of(context) 相同的对象,它会为您计算设备像素比,而上面不会。几乎相同的解决方案,但有一些额外的绒毛。
    • @Royston46 MediaQueryData.fromWindow 做了什么样的设备像素比计算?我刚刚测试过,他们都给了我相同的号码。
    【解决方案5】:

    通过重新运行应用程序解决(点击android studio中的停止按钮然后再次运行)

    【讨论】:

    • 这只有在您在两次运行之间更改了代码时才有效。
    【解决方案6】:

    更好的方法。上述解决方案需要您只有一个屏幕小部件或继承父类的所有屏幕。 但是有解决办法,将媒体查询初始化放到onGenerateRoute回调函数中

    main.dart

    import 'package:flutter/material.dart';
    
    class MyApp extends StatefulWidget {
        @override
        State<StatefulWidget> createState() => new MyAppState();
    }
    
    class MyAppState extends State<MyApp> {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'My Awesome App',
            routes: NavigationUtils.routeList(),
            onGenerateRoute: (routeSettings) =>
              NavigationUtils.onGenerateRoute(routeSettings),
          );
        }
    }
    

    NavigationUtils.dart

    import 'package:flutter/material.dart';
    
    class NavigationUtils {
        static onGenerateRoute(RouteSettings routeSettings) {   
          return new MaterialPageRoute(
            builder: (context) {
              WidgetUtils.me.init(context);
                return StorageUtils.me.isLogged() ? HomeScreen() : ForkScreen();
            },
            settings: routeSettings,
          );
        }
    }
    

    WidgetUtils.dart

    import 'package:flutter/material.dart';
    
    class WidgetUtils {
        MediaQueryData _mediaQueryData;
        double _screenWidth;
        double _screenHeight;
        double _blockSizeHorizontal;
        double _blockSizeVertical;
    
        init(BuildContext context) {
            _mediaQueryData = MediaQuery.of(context);
            screenWidth = _mediaQueryData.size.width;
            screenHeight = _mediaQueryData.size.height;
            blockSizeHorizontal = screenWidth / 100;
            blockSizeVertical = screenHeight / 100;
        }
    }
    

    警告:这不是复制和粘贴代码,有一些单例等,但你应该明白这一点;)

    【讨论】:

      【解决方案7】:

      有同样的错误

      import 'screens/tasks_screen.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return TasksScreen();
      
        }
      }
      

      我通过以下方式解决了它:-

      import 'package:flutter/material.dart';
      import 'screens/tasks_screen.dart';
      
      void main() => runApp(MyApp());
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            home: TasksScreen(),
          );
        }
      }
      

      【讨论】:

        【解决方案8】:

        将您的代码封装在 Material App 小部件中。我也遇到了同样的问题,忘记用了,直接退回了脚手架。

        换句话说,您的 MediaQuery.of(context) 应该在 Material Widget 中。 Material 应用 -> 脚手架 -> MediaQuery.of(context)

        【讨论】:

          【解决方案9】:
          void main() => runApp(MyApp());
          
          class MyApp extends StatelessWidget {
            @override
            Widget build(BuildContext context) {
              return MaterialApp(
                debugShowCheckedModeBanner: false,
                home: MyAppOne(),
              );
            }
          }
          class MyAppOne extends StatefulWidget {
            @override
            _MyAppState createState() => _MyAppState();
          }
          class _MyAppState extends State<MyAppOne>{
            @override
            Widget build(BuildContext context){
              return Scaffold(
              );
            }
          }
          

          【讨论】:

            【解决方案10】:

            MediaQueryScaffold 内部组件用来布局它的子元素,从它的source code 可以看出。因此,它需要封装在一个提供MediaQuery 的小部件中,就像一个继承自WidgetsAppMaterialApp 小部件。

            要修复您的 MediaQuery.of(context) 应该在 Material Widget 内。 Material 应用 -> 脚手架 -> MediaQuery.of(context)

            class MyApp extends StatelessWidget {
              // This widget is the root of your application.
            
              @override
              Widget build(BuildContext context) {
                return MaterialApp(
                  title: 'Loading Page',
                  theme: ThemeData(
                    primarySwatch: Colors.blue,
                  ),
                  home: MyAppPage(),
                );
              }
            }
            

            更多信息:MediaQuery.of() called with a context that does not contain a MediaQuery

            【讨论】:

              【解决方案11】:
              import 'package:flutter/material.dart';
              
              void main() => runApp(App());
              
              class App extends StatelessWidget {
              
                @override
               
               Widget build(BuildContext context) {
                  
                 return MaterialApp(
                  
                    home: Scaffold(
                    body:HomePage(),
                    ),
                  );
                 }
              
              }
              
              
              class HomePage extends StatelessWidget {
              
                @override
              
                Widget build(BuildContext context) {
              
                  var size = MediaQuery.of(context).size.height;
              
                  return Container(
                    height:size/2,
                    color:Colors.lightBlueAccent,
                      
                  );
                }
              
              }
              

              你应该试试这个我已经做到了。

              【讨论】:

                【解决方案12】:

                我试图更改包然后出现此错误, 所以请确保您完成以下每个步骤

                https://stackoverflow.com/a/51550358/4993045

                【讨论】:

                  【解决方案13】:

                  添加 MaterialApp ...

                  void main() {
                    runApp(MaterialApp(
                      home: HomePage(),
                    ));
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 2020-08-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-11-22
                    • 2019-09-05
                    • 1970-01-01
                    • 2020-07-27
                    相关资源
                    最近更新 更多