未处理的异常:未找到 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()