How do I access MediaQuery information on materialApp?

How can I access MediaQuery information on top of MaterialApp?

I need the height and width information of the device

CODE :

    final height =  MediaQuery.of(context).size.height; // I WANT TO REACH THIS !!!
    final width =  MediaQuery.of(context).size.width; // I WANT TO REACH THIS !!! IN HERE
    

    return MaterialApp(
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        home: Home(),
      
    );
  }
}

THIS IS ERROR :

FlutterError (No MediaQuery widget ancestor found. MyApp widgets require a MediaQuery widget ancestor. The specific widget that could not find a MediaQuery ancestor was: MyApp The ownership chain for the affected widget is: "MyApp ← [root]" No MediaQuery ancestor could be found starting from the context that was passed to MediaQuery.of(). This can happen because you have not added a WidgetsApp, CupertinoApp, or MaterialApp widget (those widgets introduce a MediaQuery), or it can happen if the context you use comes from a widget above those widgets.)


Upvotes: 2

Views: 1360

Answers (4)

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63569

You can use MediaQueryData.fromWindow in this case.

final queryData = MediaQueryData.fromView(WidgetsBinding.instance.platformDispatcher.implicitView!);
final height = queryData.size.height;
final width = queryData.size.width;

Upvotes: 2

Tobias Marschall
Tobias Marschall

Reputation: 2579

Let App either be MaterialApp, CupertinoApp or WidgetsApp.

Normally App creates a MediaQuery and makes it available to its decendants. Because of that there is no MediaQuery available for ancestors of App.

You can however create your own MediaQuery ancestor which gets it's data from the window using MediaQueryData.fromWindow(window). You then need to listen to metrics changes (e.g. window resize) and update the MediaQuery with the updated MediaQueryData.

Example:

import 'dart:ui';

import 'package:flutter/material.dart';

class MediaQueryProvider extends StatefulWidget {
  const MediaQueryProvider({Key? key}) : super(key: key);

  @override
  State<MediaQueryProvider> createState() => _MediaQueryProviderState();
}

class _MediaQueryProviderState extends State<MediaQueryProvider>
    with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    // Initiate a rebuild of the MediaQuery with new MediaQueryData
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return MediaQuery(
      data: MediaQueryData.fromWindow(window),
      child: Builder(builder: (context) {
        // You can now get the MediaQuery of context.
        final mediaQuery = MediaQuery.of(context);
        return const MaterialApp(useInheritedMediaQuery: false);
      }),
    );
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}

Upvotes: 0

Yunus Kocatas
Yunus Kocatas

Reputation: 316

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: MyApp1(),
      ),
    );
  }
}

class MyApp1 extends StatelessWidget {
  const MyApp1({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        color: Colors.red,
        height: MediaQuery.of(context).size.height / 2,
        width: MediaQuery.of(context).size.width / 2,
      ),
    );
  }
}

enter image description here

Upvotes: 0

Paul
Paul

Reputation: 472

It's hard to tell from such a small code excerpt, but I assume you are calling this in a build() method. MediaQuery are created by specific widgets, including WidgetsApp and MaterialApp. MediaQuery.of looks up the subtree from your widget which includes a MaterialApp, it does include one as an ancestor (up the tree).

You can fix this in a couple of ways, and they will likely improve your app's performance. One solution is to create the MaterialApp in your main() method and include everything else in your build code in the home() widget as a child of the MaterialApp. That way, the entire MaterialApp will not be rebuilt as often.

void main() {
  runApp(const MaterialApp(home: Home()));
}

You can remove the MaterialApp from your build method

final height =  MediaQuery.of(context).size.height;
final width =  MediaQuery.of(context).size.width;

print('H: $height  W: $width');

return Home();

This runs are prints out the width and height.

Upvotes: -1

Related Questions