未处理的异常:未找到 MediaQuery 小部件 - 颤振 ShowModalButtonSheet

Posted

技术标签:

【中文标题】未处理的异常:未找到 MediaQuery 小部件 - 颤振 ShowModalButtonSheet【英文标题】:Unhandled Exception: No MediaQuery widget found - flutter ShowModalButtonSheet 【发布时间】:2020-12-29 19:41:49 【问题描述】:

我正在做这个项目,在按下谷歌地图的标记(当前位置)后显示一个 showModalBottomSheet 小部件,使用标记的 onTap() 方法。但它显示异常:MyApp 小部件需要 MediaQuery 小部件祖先。

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';

void main() 
  runApp(MyApp());


class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


class _MyAppState extends State<MyApp> 
  GoogleMapController mapController;
  Position currentLocation;
  LatLng _center;
  Set<Marker> _markers = Set();

  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    setLocation();
  

  void _onMapCreated(GoogleMapController controller) 
    mapController = controller;
  

  void setLocation() async 
    currentLocation = await Geolocator()
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    setState(() 
      _center = LatLng(currentLocation.latitude, currentLocation.longitude);
    );
  

  Widget googleMap() 
    addMarkers();
    return GoogleMap(
      onMapCreated: _onMapCreated,
      myLocationEnabled: true,
      initialCameraPosition: CameraPosition(
        target: _center,
      ),
      markers: _markers,
    );
  

  void addMarkers() 
    _markers.addAll([
      Marker(
        markerId: MarkerId('current location'),
        position: _center,
        onTap: () 
          print("tapped !!!!!!");
          showModalBottomSheet(
              context: context,
              builder: (context) 
                return Text('Modal bottom sheet', style: TextStyle(fontSize: 30));
              );
        ,
      ),
    ]);
  


  @override
  Widget build(BuildContext context) 
    print("Debug: build called!!!");
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Google Map'),
          backgroundColor: Colors.blue,
        ),

        body: (_center == null)
            ? Center(child: CircularProgressIndicator())
            : googleMap(),

      ),

    );
  


我该如何解决这个问题?

【问题讨论】:

你能发布完整的错误日志吗? E/flutter (25672): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] 未处理异常:未找到 MediaQuery 小部件。 E/flutter (25672):MyApp 小部件需要 MediaQuery 小部件祖先。 E/flutter (25672):找不到 MediaQuery 祖先的特定小部件是:E/flutter (25672):MyApp E/flutter (25672):受影响小部件的所有权链是:“MyApp ← [root]” E/flutter (25672):通常,MediaQuery 小部件由应用程序小部件树顶部的 MaterialApp 或 WidgetsApp 小部件引入。 【参考方案1】:

这对我有用。我将 MyApp StatefulWidget 重命名为 Home 并创建了一个 StatelessWidget 并将其命名为 MyApp。然后我将 Home StatefulWidget 传递给 MyApp StatelessWidget 的 home 属性。

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(home: Home());
  


class Home extends StatefulWidget 
  @override
  _HomeState createState() => _HomeState();


class _HomeState extends State<Home> 
  GoogleMapController mapController;
  Position currentLocation;
  LatLng _center;
  Set<Marker> _markers = Set();

  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    setLocation();
  

  void _onMapCreated(GoogleMapController controller) 
    mapController = controller;
  

  void setLocation() async 
    currentLocation = await Geolocator()
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    setState(() 
      _center = LatLng(currentLocation.latitude, currentLocation.longitude);
    );
  

  Widget googleMap() 
    addMarkers();
    return GoogleMap(
      onMapCreated: _onMapCreated,
      myLocationEnabled: true,
      initialCameraPosition: CameraPosition(
        target: _center,
      ),
      markers: _markers,
    );
  

  void addMarkers() 
    _markers.addAll([
      Marker(
        markerId: MarkerId('current location'),
        position: _center,
        onTap: () 
          print("tapped !!!!!!");
          showModalBottomSheet(
              context: context,
              builder: (context) 
                return Center(
                  child: Text('Modal bottom sheet',
                      style: TextStyle(fontSize: 30)),
                );
              );
        ,
      ),
    ]);
  

  @override
  Widget build(BuildContext context) 
    print("Debug: build called!!!");
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Google Map'),
          backgroundColor: Colors.blue,
        ),
        body: (_center == null)
            ? Center(child: CircularProgressIndicator())
            : googleMap(),
      ),
    );
  

【讨论】:

非常感谢!你能解释一下为什么我的代码会出现这样的问题吗? 不客气@Roslin!我对您的问题没有明确的答复,但据我所知,ShowModalButtonSheet 不应与 MaterialApp 处于同一级别,因此我尝试将它们分开,它对我有用 如果我的回答也对您有用并且有帮助,请接受它。谢谢!【参考方案2】:

我使用在 Builder 中返回 google map 小部件并引用 builder 上下文解决了这个问题

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:android_intent/android_intent.dart';


void main() 
  runApp(MyApp());


class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


class _MyAppState extends State<MyApp> 
  GoogleMapController mapController;
  LatLng _currentPosition;
  Set<Marker> _markers = Set();

  // Obtaining current location coordinate & setting it
  void setLocation() async 
    bool isLocationEnabled = await Geolocator().isLocationServiceEnabled();

    if(!isLocationEnabled)
      openLocationSetting();
    

    Position currentLocation = await Geolocator()
        .getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    setState(() 
      _currentPosition =
          LatLng(currentLocation.latitude, currentLocation.longitude);
    );
  

  // Open Location Setting if GPS not enabled
  void openLocationSetting() async 
    final AndroidIntent intent = new AndroidIntent(
      action: 'android.settings.LOCATION_SOURCE_SETTINGS',
    );
    await intent.launch();
  

  // initializing _currentPosition state.
  @override
  void initState() 
    // TODO: implement initState
    super.initState();
    // Initiate full screen
    SystemChrome.setEnabledSystemUIOverlays([]);
    // Initiate current location
    setLocation();
  

  void showModal(BuildContext context) 
    final _formKey = GlobalKey<FormState>();
    final nameController = TextEditingController();
    final locationController = TextEditingController();

    locationController.text = _currentPosition.latitude.toString() +
        "," +
        _currentPosition.longitude.toString();

    // Showing modal with Name & Current location input form to send data to console
    showModalBottomSheet(
        context: context,
        isScrollControlled: true,
        builder: (BuildContext context) 
          return SingleChildScrollView(
              child: Container(
            padding: EdgeInsets.only(
                bottom: MediaQuery.of(context).viewInsets.bottom),
            child: Form(
              key: _formKey,
              child: Wrap(
                children: <Widget>[
                  TextFormField(
                    decoration: InputDecoration(
                      hintText: 'Enter your current location',
                    ),
                    controller: locationController,
                    validator: (value) 
                      if (value.isEmpty) 
                        return 'Please enter some text';
                      
                      return null;
                    ,
                  ),
                  TextFormField(
                    decoration: InputDecoration(
                      hintText: 'Enter your name',
                    ),
                    controller: nameController,
                    validator: (value) 
                      if (value.isEmpty) 
                        return 'Please enter some text';
                      
                      return null;
                    ,
                  ),
                  RaisedButton(
                    onPressed: () 
                      if (_formKey.currentState.validate()) 
                        debugPrint(nameController.text);
                        debugPrint(locationController.text);
                      
                    ,
                    child: Text('Send'),
                  )
                ],
              ),
            ),
          ));
        );
  

  void _onMapCreated(GoogleMapController controller) 
    mapController = controller;
  

  // Adding markers in Google map for current location
  void addMarkers(BuildContext context) 
    _markers.addAll([
      Marker(
        markerId: MarkerId('Current Location'),
        position: _currentPosition,
        onTap: () 
          showModal(context);
        ,
      ),
    ]);
  

  // Building Google map widget & pointing initial position to current position
  Widget googleMap(BuildContext context) 
    addMarkers(context);
    return GoogleMap(
      onMapCreated: _onMapCreated,
      myLocationEnabled: true,
      initialCameraPosition: CameraPosition(
        target: _currentPosition,
      ),
      markers: _markers,
    );
  

  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text('Google Map'),
            backgroundColor: Colors.teal,
          ),
          body: Builder(
            builder: (context) 
              return (_currentPosition == null)
                  ? Center(child: CircularProgressIndicator(),)
                  : googleMap(context);
            ,
          )),
    );
  


【讨论】:

以上是关于未处理的异常:未找到 MediaQuery 小部件 - 颤振 ShowModalButtonSheet的主要内容,如果未能解决你的问题,请参考以下文章

Flutter - 从 websocket 消息动态创建小部件 - 未处理的异常:在构造函数中调用 setState()

在 InitState 未处理异常中显示对话框:查找已停用小部件的祖先是不安全的

未找到材质小部件 文本字段小部件需要材质小部件祖先

未找到材质小部件

服务门户小部件表单返回“未找到记录”

颤振未找到材料小部件