Flutter Error: MediaQuery.of() called with a context that does not contain a MediaQuery
Asked Answered
I

13

91

I have been trying to get the size of the whole context view in Flutter. But every time I try I'm getting the above mentioned error. Here's my code:

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(),
    );
  }
}

Note: I also tried with a StatefulWidget. Please, help me find what I'm doing wrong here.

Inerney answered 7/5, 2018 at 12:32 Comment(4)
How do you show the page?Masto
void main() => runApp(new MyIntroductionPage());Inerney
Can you show the exact error? PS: don't keep size as final, because it may change when you rotate the phone.Pipage
@ArnoldParge the exact error is given in the title itself.Inerney
T
105

You need a MaterialApp or a WidgetsApp around your widget. They provide the MediaQuery. When you call .of(context) flutter will always look up the widget tree to find the widget.

You usually have this in your 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: ...,
    );
  }
}
Tartu answered 7/5, 2018 at 12:58 Comment(4)
I have just seen your edits. When you call MediaQuery.of(context), the MaterialApp must already be in the widget three.Tartu
I had same problem but just in first run i had this error and second run and more works correctly.Durmast
Encountered the same question as @MohammadMeshkani mentioned, error disappear at second runResponsion
Still i am having this problem.Keyte
P
26

What works for us is using WidgetsBinding.instance.window instead of MediaQuery - also when setting the theme of the 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;
Preindicate answered 26/2, 2020 at 13:42 Comment(4)
two different result in WidgetsBinding.instance.window.padding.top and MediaQuery.of(context).padding.top;Atonement
@BloodLoss You can use WidgetsBinding.instance.window.viewPadding insteadEllissa
MediaQueryData.fromWindow(WidgetsBinding.instance.window) gives you the same object back as MediaQuery.of(context) and it does the device pixel ratio calculations for you, which the above won't. Pretty much the same solution but with some extra fluff.Fishbowl
@Fishbowl What kind of device pixel ratio calculations does MediaQueryData.fromWindow do? I just tested it and they both gave me the same number.Reest
P
20

You can access MediaQuery when you are inside MaterialApp. The place where you are accessing the media query is not correct.

Please refer below code:

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();
  }
}

I've purposely created a class CommonThings which has static Size so that you can use it throughout the app.

Pipage answered 7/5, 2018 at 14:53 Comment(0)
I
16

I fixed it by using the following method. First I created a new class named MyWidget and returned it in MyApp within a MaterialApp's home:. Refer code below:

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(),
    );
  }
} 

Also, declaring size as final doesn't matter. Orientation/Rotation is handled.

Inerney answered 8/5, 2018 at 4:24 Comment(1)
What a weird behaviour. Used WidgetsBinding.instance.window.physicalSize insteadProglottis
L
12

Solved by re-run the app(click on stop button in android studio then run again)

Leakage answered 21/11, 2019 at 10:22 Comment(1)
This will only work if you changed your code in between those runs.Reest
S
5

There is better way. Above solutions would require you to have only one screen widget or inherit all screens from parent class. But there is solution, place the media query initialization into onGenerateRoute callback function

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;
    }
}

Warning: It is not copy & paste code, there are some singletons etc. but you should get the point ;)

Specialistic answered 4/8, 2019 at 10:10 Comment(0)
M
4

Had the same error in

import 'screens/tasks_screen.dart';

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

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

  }
}

I solved it by:-

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(),
    );
  }
}
Metasomatism answered 16/1, 2020 at 8:46 Comment(0)
P
3

Wrap your code in a Material App widget. I also had the same issue as I forgot to use it and directly returned the scaffold.

In other words, your MediaQuery.of(context) should be inside the Material Widget. Material app -> scaffold -> MediaQuery.of(context)

Pelotas answered 21/7, 2019 at 6:49 Comment(0)
B
3
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(
    );
  }
}
Bainite answered 20/8, 2019 at 16:44 Comment(0)
K
2
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,
        
    );
  }

}

YOU SHOULD TRY THIS I HAVE DONE IT.

Klutz answered 22/10, 2020 at 7:53 Comment(0)
T
1

I was trying to change the package then this error arise, so make sure you complete each of the following steps

https://mcmap.net/q/73892/-how-to-change-package-name-in-flutter

Thunderstorm answered 6/6, 2020 at 8:23 Comment(0)
P
0

As WidgetsBinding.instance.window... is deprecated use FlutterView instead:

  static void _loadDeviceInfos() {
    FlutterView view = WidgetsBinding.instance.platformDispatcher.views.first;
    _pixelRatio = view.devicePixelRatio;
    _screenWidth = view.physicalSize.width;
    _screenHeight = view.physicalSize.height;
    _statusBarHeight = view.padding.top;
    _bottomBarHeight = view.padding.bottom;
  }
Preindicate answered 12/9, 2023 at 15:39 Comment(0)
W
-2

Add MaterialApp ...

void main() {
  runApp(MaterialApp(
    home: HomePage(),
  ));
}
Whitten answered 6/4, 2019 at 1:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.