web-dev-qa-db-fra.com

Erreur de flottement: MediaQuery.of () appelée avec un contexte qui ne contient pas de MediaQuery

J'ai essayé d'obtenir la taille de la vue contextuelle entière dans Flutter. Mais chaque fois que j'essaye, j'obtiens l'erreur mentionnée ci-dessus. Voici mon 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: J'ai aussi essayé avec un StatefulWidget. S'il vous plaît, aidez-moi à trouver ce que je fais mal ici.

23
Bibin Jacob

Vous avez besoin d'un MaterialApp ou d'un WidgetsApp autour de votre widget. Ils fournissent le MediaQuery. Lorsque vous appelez .of(context) flutter recherchera toujours l’arborescence des widgets pour trouver le widget.

Vous avez généralement ceci dans votre 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: ...,
    );
  }
}
31
Ian

Vous pouvez accéder à MediaQuery lorsque vous êtes à l'intérieur de MaterialApp. L'endroit où vous accédez à la requête multimédia n'est pas correct.

Veuillez vous référer au code ci-dessous:

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

J'ai volontairement créé une classe CommonThings qui a une taille statique afin que vous puissiez l'utiliser dans toute l'application.

3
Arnold Parge

Je l'ai corrigé en utilisant la méthode suivante. Tout d'abord, j'ai créé une nouvelle classe nommée MyWidget et je l'ai renvoyée dans MyApp à l'intérieur d'un MaterialApphome:. Référence code ci-dessous:

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

De plus, déclarer la taille comme finale n'a pas d'importance. L'orientation/rotation est gérée.

3
Bibin Jacob

Il y a meilleure façon. Les solutions ci-dessus vous obligeraient à avoir n seul widget d'écran ou hériter tous les écrans de la classe parente. Mais il existe une solution, placez l'initialisation de la requête multimédia dans la fonction de rappel 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;
    }
}

Attention: ce n’est pas du code copier-coller, il y a des singletons etc. mais vous devriez avoir le point;)

0
Srneczek
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(
);
}
}
0
Shubhanshu Singh

Enveloppez votre code dans un widget Application matérielle. J'ai également eu le même problème car j'ai oublié de l'utiliser et j'ai directement renvoyé l'échafaudage.

En d'autres termes, votre MediaQuery.of (contexte) doit être à l'intérieur du widget Matériel. Application matérielle -> échafaudage -> MediaQuery.of (contexte)

0
Mahi