Flutter:在用户输入时显示标记信息窗口抛出 PlatformException

Posted

技术标签:

【中文标题】Flutter:在用户输入时显示标记信息窗口抛出 PlatformException【英文标题】:Flutter: display Marker information window upon user's input throws PlatformException 【发布时间】:2021-04-21 00:28:22 【问题描述】:

我正在实现这个应用程序,用户可以在其中插入他们的街道地址和城市,并且该位置将显示在地图上。我正在使用Google Maps package 来显示地图。

我想要的行为是,当用户提交位置时 - 地图将聚焦在提交的位置上,Marker 将与其InfoWindow 一起显示。

我试图实现它,但由于某种原因,我的代码总是抛出异常(下面标有FIXME: 的有问题的代码行):

E/flutter (23235): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: PlatformException(Invalid markerId, showInfoWindow called with invalid markerId, null, null)

在线查找问题并没有产生任何结果。有人遇到过这样的问题吗?

pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  intl: ^0.16.1
  provider: ^4.3.2+2
  google_fonts: ^1.1.1
  cupertino_icons: ^1.0.0
  collection: ^1.14.13
  cached_network_image: ^2.5.0
  fluttertoast: ^7.1.6
  shared_preferences: ^0.5.12+4
  flutter_staggered_animations: "^0.1.2"
  badges: ^1.1.6
  google_maps_flutter: ^1.1.1
  location: ^3.0.0
  geocoder: ^0.2.1

我的代码:

final TextEditingController _googleStreetController = TextEditingController();
final TextEditingController _googleCityController = TextEditingController();
final FocusNode _googleStreetInputFocusNode = FocusNode();
final FocusNode _googleCityInputFocusNode = FocusNode();

/// Google Map controller
Completer<GoogleMapController> _googleMapsController = Completer();

/// initial camera position of the map - set to 5th avenue, NYC
static const LatLng _center = const LatLng(40.75476210819693, -73.98163492275201);

/// set of map markers that user inserted
final Set<Marker> _markers = ;

/// method that is called on map creation and takes a MapController as a parameter.
Future<void> _onMapCreated(GoogleMapController controller) async 
  setState(() 
    _googleMapsController.complete(controller);
  );
  if(_markers.isEmpty)
    return;
  
  var marker = _markers.first;
  double lat = marker.position.latitude;
  double long = marker.position.longitude;
  var c = await _googleMapsController.future;
  await c.moveCamera(CameraUpdate.newLatLng(LatLng(lat, long)));
  await c.showMarkerInfoWindow(marker.markerId);
  setState(() 

  );


InputDecoration _getInputDecoration(String hint) 
  return InputDecoration(
    enabledBorder: _getOutlineInputBorder(),
    focusedBorder: _getOutlineInputBorder(color: Colors.lightGreen.shade800),
    hintText: hint,
    suffixIcon: hint == 'City'
      ? Icon(Icons.location_city_outlined)
      : Icon(Icons.home_outlined),
    contentPadding: EdgeInsets.fromLTRB(5.0 , 5.0 , 5.0 , 5.0),
  );


OutlineInputBorder _getOutlineInputBorder(Color color = Colors.grey) 
  return OutlineInputBorder(
    borderSide: BorderSide(
      color: color,
      width: 1.3,
    ),
    borderRadius: BorderRadius.all(Radius.circular(30)),
  );


bool _isAddressEmpty()
  return _googleStreetController.text.isEmpty || _googleCityController.text.isEmpty;


///removing focus from all text field's
void _unfocusAll()
  _googleCityInputFocusNode.unfocus();
  _googleStreetInputFocusNode.unfocus();


@override
Widget build(BuildContext context) 
  return Material(
    child: Center(
      child: IconButton(
        iconSize: 27.0, ///<-- default is 24.0
        icon: Icon(Icons.favorite),
        onPressed: () 
          showDialog(
            context: context,
            barrierDismissible: true,
            builder: (context) 
              return Center(
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: GestureDetector(
                    onTap: () 
                      FocusScope.of(context).unfocus();
                    ,
                    child: ClipRRect(
                      borderRadius: BorderRadius.all(Radius.circular(20.0)),
                      child: Material(
                        child: Container(
                          color: Colors.transparent,
                          height: MediaQuery.of(context).size.height * 0.8,
                          width: MediaQuery.of(context).size.width,
                          child: Column(
                            mainAxisSize: MainAxisSize.min,
                            mainAxisAlignment: MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,
                            children: <Widget>[
                              Flexible(
                                flex: 5,
                                child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: <Widget>[
                                    Flexible(
                                      flex: 4,
                                      child: Padding(
                                        padding: const EdgeInsets.only(
                                          left: 8.0,
                                          right: 4.0,
                                          top: 12.0,
                                          bottom: 9.0,
                                        ),
                                        child: TextField(
                                          controller: _googleStreetController,
                                          decoration: _getInputDecoration('Street'),
                                          style: GoogleFonts.lato(
                                            fontWeight: FontWeight.w600,
                                            fontSize: 16.0,
                                          ),
                                          focusNode: _googleStreetInputFocusNode,
                                          autofocus: false,
                                          textAlign: TextAlign.start,
                                          textAlignVertical: TextAlignVertical.center,
                                          keyboardType: TextInputType.streetAddress,
                                          inputFormatters: [
                                            FilteringTextInputFormatter.allow(RegExp('[a-z A-Z 0-9 .]'))
                                          ],
                                        ),
                                      ),
                                    ),
                                    Flexible(
                                      flex: 3,
                                      child: Padding(
                                        padding: const EdgeInsets.only(
                                          left: 4.0,
                                          right: 4.0,
                                          top: 12.0,
                                          bottom: 9.0,
                                        ),
                                        child: TextField(
                                          controller: _googleCityController,
                                          decoration: _getInputDecoration('City'),
                                          style: GoogleFonts.lato(
                                            fontWeight: FontWeight.w600,
                                            fontSize: 16.0,
                                          ),
                                          keyboardType: TextInputType.streetAddress,
                                          inputFormatters: [
                                            FilteringTextInputFormatter.allow(RegExp('[a-z A-Z .]'))
                                          ],
                                          focusNode: _googleCityInputFocusNode,
                                          autofocus: false,
                                          textAlign: TextAlign.start,
                                          textAlignVertical: TextAlignVertical.center,
                                        ),
                                      ),
                                    ),
                                    Flexible(
                                      flex: 1,
                                      child: Padding(
                                        padding: const EdgeInsets.only(bottom: 9.0),
                                        child: Column(
                                          mainAxisSize: MainAxisSize.min,
                                          crossAxisAlignment: CrossAxisAlignment.center,
                                          mainAxisAlignment: MainAxisAlignment.start,
                                          children: <Widget>[
                                            Flexible(
                                              flex: 2,
                                              child: IconButton(
                                                icon: Icon(
                                                  Icons.add_location_alt,
                                                  color: Colors.deepOrange,
                                                  size: 27.0,
                                                ),
                                                onPressed: () async 
                                                  _unfocusAll();
                                                  if(_isAddressEmpty())
                                                    Fluttertoast.showToast(
                                                      msg: 'Please choose address'
                                                    );
                                                    return;
                                                  
                                                  List<Address> locations = <Address>[];
                                                  try
                                                    locations = await Geocoder.local.findAddressesFromQuery(
                                                        _googleStreetController.text.trim() + ' ' + _googleCityController.text.trim()
                                                    );
                                                   on PlatformException catch (_)
                                                    Fluttertoast.showToast(
                                                      msg: 'Invalid address'
                                                    );
                                                    return;
                                                  
                                                  if(locations.isEmpty)
                                                    Fluttertoast.showToast(
                                                      msg: 'Invalid address'
                                                    );
                                                    return;
                                                  
                                                  var first = locations.first;
                                                  // print('$first.locality');
                                                  // print('$first.adminArea');
                                                  // print('$first.subLocality');
                                                  // print('$first.subAdminArea');
                                                  // print('$first.addressLine');
                                                  // print(' $first.thoroughfare');
                                                  // print('$first.subThoroughfare');
                                                  var coordinates = LatLng(first.coordinates.latitude, first.coordinates.longitude);
                                                  _markers.clear();
                                                  setState(() 
                                                    _markers.add(
                                                      new Marker(
                                                        markerId: MarkerId(coordinates.toString()),
                                                        draggable: false,
                                                        visible: true,
                                                        position: coordinates,
                                                        icon: BitmapDescriptor.defaultMarker,
                                                        infoWindow: InfoWindow(
                                                          title: first.thoroughfare + ' ' + (first?.subThoroughfare ?? ''),
                                                          snippet: first.locality + ', ' + first.adminArea + ', ' + first.countryName,
                                                        )
                                                      )
                                                    );
                                                  );
                                                  var marker = _markers.first;
                                                  print(marker.toString());
                                                  print(marker.markerId);
                                                  double lat = marker.position.latitude;
                                                  double long = marker.position.longitude;
                                                  var c = await _googleMapsController.future;
                                                  await c.moveCamera(CameraUpdate.newLatLng(LatLng(lat, long)));
                                                  ///FIXME: throwing unsupported exception
                                                  await c.showMarkerInfoWindow(marker.markerId);
                                                  setState(() );
                                                
                                              ),
                                            ),
                                            Flexible(
                                              flex: 1,
                                              child: Text('Add',
                                                style: GoogleFonts.lato(
                                                  fontSize: MediaQuery.of(context).size.height * 0.0256 * (12/18) + 0.4,
                                                  fontWeight: FontWeight.w600
                                                ),
                                              ),
                                            ),
                                          ],
                                        ),
                                      )
                                    ),
                                  ],
                                ),
                              ),
                              Flexible(
                                flex: 33,
                                child: GoogleMap(
                                  markers: _markers,
                                  onTap: (LatLng details)
                                    _unfocusAll();
                                  ,
                                  onMapCreated: (c) async 
                                    await _onMapCreated(c);
                                  ,
                                  initialCameraPosition: CameraPosition(
                                    target: _center,
                                    zoom: 15.0,
                                  ),
                                ),
                              ),
                              Flexible(
                                flex: 4,
                                child: Center(
                                  child: OutlineButton.icon(
                                    onPressed: () 
                                      if(_isAddressEmpty())
                                        Fluttertoast.showToast(
                                          msg: 'Please choose address'
                                        );
                                        return;
                                      
                                    ,
                                    icon: Icon(
                                      Icons.map,
                                      color: Colors.black,
                                      size: MediaQuery.of(context).size.height * 0.0256 * 25/18,
                                    ),
                                    label: Text(
                                      'Submit chosen location',
                                      textAlign: TextAlign.center,
                                      style: GoogleFonts.lato(
                                        fontSize: MediaQuery.of(context).size.height * 0.0256 * 16/18,
                                        fontWeight: FontWeight.w600,
                                      ),
                                    ),
                                    borderSide: BorderSide(
                                      color: Colors.black,
                                      width: 1.5,
                                    ),
                                    shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(30.0),
                                    ),
                                  ),
                                ),
                              )
                            ],
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
              );
            
          );
        
      )
    )
  );



@override
void dispose() 
  _googleCityInputFocusNode.dispose();
  _googleStreetInputFocusNode.dispose();
  _googleCityController.dispose();
  _googleStreetController.dispose();
  super.dispose();

【问题讨论】:

亲爱的AK-23,你能找到解决这个问题的办法吗? 【参考方案1】:

替换

markerId: MarkerId(coordinates.toString()),

markerId: MarkerId("$coordinates.latitude"),

它将解决您的问题。

【讨论】:

很遗憾,出现同样的错误异常。 这个问题有什么解决办法吗?

以上是关于Flutter:在用户输入时显示标记信息窗口抛出 PlatformException的主要内容,如果未能解决你的问题,请参考以下文章

在vscode中调试flutter App时显示错误

如何在 Flutter 中获取当前位置时显示加载微调器?

linux在终端输入密码时显示星号的实现方法

电脑关机时显示应用程序错误

命令行输入窗口用mysqldump备份时显示can't connect to mysql server on"localhost"when trying connect

Flutter HTTP 响应在 Flutter web 上测试时显示完整响应,但在 Android 设备上测试时显示不完整