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

时间:2020-09-11 09:33:35

标签: android google-maps flutter

我正在使用这个Marker的onTap()方法在按下Google Maps的标记(当前位置)之后显示一个 showModalBottomSheet 小部件。但它显示异常: 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(),

      ),

    );
  }
}

我该如何解决?

2 个答案:

答案 0 :(得分:1)

enter image description here

这对我有用。我将 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(),
      ),
    );
  }
}

答案 1 :(得分:0)

我通过在Builder内部返回google map小部件并引用构建器上下文来解决此问题

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