如何在 flutter web 中检测用户位置并显示地址

2024-01-22

我的 flutter web 应用程序的地理位置和地理编码不起作用。我在该站点的一些答案后进行编码,以检测用户的位置,显示地址并将地址信息传递到下一页。我做了2页。在我的“地理定位”页面上,我制作了 2 个按钮。我想在用户单击第一个按钮时显示用户的地址。当他/她单击第二个按钮时,我想保存地址信息并传递到下一页。我怎么做?如果您了解 flutter web,请给我一些提示。 这是我的页面之一“locationjs.dart”;

    @JS('navigator.geolocation') // navigator.geolocation 
      namespace
    library jslocation; // library name can be whatever you 
    want

    import "package:js/js.dart";

    @JS('getCurrentPosition') // Accessing method 
     getCurrentPosition from       Geolocation API
     external void getCurrentPosition(Function 
     success(GeolocationPosition pos));

    @JS()
    @anonymous
    class GeolocationCoordinates {
    external double get latitude;
    external double get longitude;
    external double get altitude;
    external double get accuracy;
    external double get altitudeAccuracy;
    
    external factory GeolocationCoordinates(
    {double latitude,
     double longitude,
  double altitude,
  double accuracy,
  double altitudeAccuracy,
  });
  }

  @JS()
  @anonymous
  class GeolocationPosition {
  external GeolocationCoordinates get coords;

  external factory 
  GeolocationPosition({GeolocationCoordinates coords});
  }

其次,我对屏幕页面进行了如下编码。在屏幕上,单击第一个按钮用于获取经度和纬度并显示用户的地址,第二个按钮用于保存信息并转到下一页。我应该写什么来做到这一点?

   import 'package:flutter/foundation.dart';
   import 'package:practice/models/user.dart';
   import 'package:practice/shared/choice.dart';
   import 'package:practice/shared/locationJs.dart';
   import 'package:flutter/material.dart';
   import 'package:js/js.dart';
   import 'package:geolocator/geolocator.dart';

  class Geolocating extends StatefulWidget {
  @override
  _GeolocatingState createState() => _GeolocatingState();
   }

  class _GeolocatingState extends State<Geolocating> {
 User user = User();
   
  void getCurrentPosition() async {
  Position position = await Geolocator()
    .getCurrentPosition(desiredAccuracy: 
  LocationAccuracy.low);

  print(position);
  }

  @override
  Widget build(BuildContext context) {
   return Scaffold(
     body: Center(
      child: Container(
        child: Column(
          children: [
            RaisedButton(child: Text('GPS coordinates'),
               onPressed: () {
               _getCurrentLocation();//get location and show address
              }),
            RaisedButton(
               child: Text('address confirmed'),
               onPressed: () {//save the info and pass to next page
               userModel.address = 
                _getCurrentLocation.toString();
               Navigator.push(context,
                    MaterialPageRoute(
                        builder: (context) => 
               NextPage(userModel: userModel)));
              }),
             ],
            ),
           ),
          ),
         );
        }
       }

 success(pos) {
  try {
  Text(pos.coords.latitude);
  Text(pos.coords.longitude);
} catch (ex) {
  print("Exception thrown : " + ex.toString());
 }
}

 _getCurrentLocation() {
   if (kIsWeb) {
   getCurrentPosition(allowInterop((pos) => success(pos)));
  }
}

我还用 2 个按钮上传了我的屏幕截图;https://i.stack.imgur.com/gGNyo.jpg https://i.stack.imgur.com/gGNyo.jpg


我希望这个解决方案可能有所帮助 - 并且我相信它可以得到改进。我想下面的图片描述了你想要做的事情。

主屏幕如下。

您想按 2 个按钮之一来显示地址,如下所示。

最后你想按第二个按钮进入下一页并显示地址,如下所示:

解决步骤如下:

  1. 利用locatioJS.dart但对其进行调整,以便它可以返回纬度和经度

  2. 使用 Future 将经度和纬度保存在列表中。

  3. 使用 Map Box API 检索给定纬度和经度的地址(反向地理编码)。

在最后一步mapbox-地理编码 https://pub.dev/packages/mapbox_geocoding and mapbox-搜索 https://pub.dev/packages/mapbox_search虽然用于反向地理编码Mapbox-Geocoding似乎运作良好 -map-box search为了完整性,反向地理编码也包含在解决方案中,也许它可能对其他人有用。请注意,在编写此解决方案时Geocoder https://pub.dev/packages/geocoder/example and 地理定位器 https://pub.dev/packages/geolocator似乎不太适合 flutter web。

我很快就会在这里提供完整的代码。(享受吧!)

Dependencies

cupertino_icons: ^1.0.0
js: ^0.6.2
mapbox_search: ^2.0.1+1
mapbox_geocoding: ^0.1.3

locatioJS.dart

// Change the line below
external void  getCurrentPosition(success(GeolocationPosition pos));
// To this one 
external void  getCurrentPosition(Future<void> 
success(GeolocationPosition pos));

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'locationJs.dart';
import 'package:js/js.dart';
import 'package:mapbox_search/mapbox_search.dart';
import 'package:mapbox_geocoding/mapbox_geocoding.dart';
import 'package:mapbox_geocoding/model/reverse_geocoding.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Provide a function to handle named routes. Use this function to
        // identify the named route being pushed, and create the correct
        // Screen.
        onGenerateRoute: (settings) {
          // If you push the PassArguments route
          if (settings.name == PassArgumentsScreen.routeName)  {
            // Cast the arguments to the correct type: ScreenArguments.
            final ScreenArguments args = settings.arguments;

            // Then, extract the required data from the arguments and
            // pass the data to the correct screen.
            return MaterialPageRoute(
              builder: (context) {
                return PassArgumentsScreen(
                  title: args.title,
                  message: args.message,
                );
              },
            );
          }
          // The code only supports PassArgumentsScreen.routeName right now.
          // Other values need to be implemented if we add them. The assertion
          // here will help remind us of that higher up in the call stack, since
          // this assertion would otherwise fire somewhere in the framework.
         assert(false, 'Need to implement ${settings.name}');
         return null;
        },
        title: 'Navigation with Arguments',
        home: HomeScreen(),
      
      
        );
  }
}

class HomeScreen extends StatefulWidget {
@override 
_HomeScreen createState() => new _HomeScreen();
}


class _HomeScreen extends State<HomeScreen> {
 
  // variables for keeoing track of state
  bool loading = false;
  List mylatlong ;  // store lat long here
  String currentAddress = 'Not found';  // for the address
  bool pressGeoON = false;  // for keeping track of button state
  bool cmbscritta = false;  // for keeping track of button state
/////////////////////////////////////////////////////////////////////////////////////
     // this sets up the map box api .//
     // open map box account. Then go to your dashboard and copy the APIKey or Token
    //Set up a test api key before running for maboxsearch package
     String apiKey = "paste your Mapbox API key (Token ) here"; 
    // Map-box geocoding requires the initialisation below
     MapboxGeocoding geocoding = MapboxGeocoding("paste your Mapbox API key (Token ) here");     //////////////////////////////////////////////////////////////////////////////////////////
  // set the information needed the lat long here 
  Future _getUserInfo() async {
        setState(() {
          loading = true;
        });
         // call loc here to initiate and get the lat long
         // loc is defined down in the code : line 109
          loc();
        setState(() {
          loading = false;
        });
        
    }

  // function for succesful collecting the lat long 
  success(pos) async   {
          List mypos;
          try {
          //print(pos.coords.latitude); 
          //print(pos.coords.longitude);
          mypos = [pos.coords.latitude, pos.coords.longitude ];                
          } catch (ex) {
            print("Exception thrown : " + ex.toString());
            //user = await GetUserInfo.getInfo(kola);
          }
        // once the lat long is retrieved set the values and sassign to th my lat logn variable
        setState(() {
            mylatlong =   mypos;
            print(mylatlong);
          });       
 }

// define future for getting the lat long
// loc is called in getUserInfo (line 78) which is in turn called in initState
Future<void> loc()  async {
  //check if web.
   if (kIsWeb) {
    // get the the lat long by calling success.  Note allowInterop 
    // which enables Returns a wrapper around a function f  that can be called from JavaScript using package:js 
    // cross check the definition of getCurrentPosition in locatioJS.dart (line 7)
   getCurrentPosition(allowInterop((pos) => success(pos)));
  
  }
 
}

//Reverse geocoding package for getting city name. Get place/city name from latitude and longitude.
  getCity(double lat, double lng) async {
  
    try {
      ReverseGeocoding reverseModel =
          await geocoding.reverseModel(lat, lng, limit: 7, types: 'region'); //types can be region, district, neighborhood see https://docs.mapbox.com/api/search/#data-types
      print(reverseModel.features[0].placeName);
      return (reverseModel.features[0].placeName);
    } catch (Excepetion) {
      return 'Reverse Geocoding Error';
    }
  }

// this future to get getAddressFromLatLng  to return the city name
Future<void> testkey() async {
  await getAddressFromLatLng(apiKey).catchError(print);
  //await placesSearch(apiKey).catchError(print);
}

// the function icalls geocity and uses it to get city name/address
Future getAddressFromLatLng(String apiKey) async {
  
  // *********** using map box search ********************************//
  // this gives empty string sometimes
  // initialise mapbox search api
  var geoCodingService = ReverseGeoCoding(
    apiKey: apiKey,
    //country: "BR",
    limit: 5,
  );
  // get the lat ling stores in the variable mylatlong (line 72) . My latlong is set by loc (line 119)
  var lat = mylatlong[0];
  var long = mylatlong[1];
  // get the address
  var addresses = await geoCodingService.getAddress(Location(
    lat: lat, //-19.984846,
    lng: long , //-43.946852,
  ));
 print(addresses); // print to view resulta
// ***********map box searxh ends here ********************************//

// *********** using map box geocoding ********************************//
// this calls th geoCity function (line 133) and uses map  geocoding to retrieve 
 var newadr = await getCity(lat, long);
  print('the mapbox geocoding api returns $newadr');
// *********** using map box geocoding ********************************//

// set the address to the value returned by mapbox geocoding 
  setState(() {
             currentAddress = newadr ;
          });
/////////////////////////////////////////

}

@override
  void initState() {

    _getUserInfo();
    super.initState();

  }
  @override
  Widget build(BuildContext context) {
   
    
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // A button that navigates to a named route that. The named route
            // extracts the arguments by itself.
            ElevatedButton(
              child: Text("Go to Page 2"),
              onPressed: () {
                 testkey();
                // When the user taps the button, navigate to a named route
                // and provide the arguments as an optional parameter.
                Navigator.pushNamed(

                  
                  context,
                  PassArgumentsScreen.routeName,
                  arguments: ScreenArguments(
                    'Welcome to page 2 ',
                    'This was retrieved from lat long $mylatlong and your adress is $currentAddress',
                  ),
                );
                //getAddressFromLatLng();
               
              },
            ),
            // A button that navigates to a named route. For this route, extract
            // the arguments in the onGenerateRoute function and pass them
            // to the screen.
            ElevatedButton(
              child: cmbscritta ? Text("Geolocation is $mylatlong , address $currentAddress ") : Text("Display lat long"), //Text("Navigate to a named that accepts arguments"),
              onPressed: () {
                // When the user taps the button, navigate to a named route
                // and provide the arguments as an optional parameter.
                testkey();
                setState(() {
                pressGeoON = !pressGeoON;
                cmbscritta = !cmbscritta;
                
                //getAddressFromLatLng();
              });
              
              },
            ),
          ],
        ),
      ),
    );
  }
}
class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;

  // This Widget accepts the arguments as constructor parameters. It does not
  // extract the arguments from the ModalRoute.
  //
  // The arguments are extracted by the onGenerateRoute function provided to the
  // MaterialApp widget.
  const PassArgumentsScreen({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}
// You can pass any object to the arguments parameter. In this example,
// create a class that contains both a customizable title and message.
class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

请随意调整它以适应您想要实现的目标。

Best.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 flutter web 中检测用户位置并显示地址 的相关文章

随机推荐