Reputation: 372
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
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
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
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,
),
);
}
}
Upvotes: 0
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