【问题标题】:HERE API Autosuggest Geocoding searchHERE API 自动建议地理编码搜索
【发布时间】:2022-11-07 17:29:40
【问题描述】:

我希望使用 HERE 地理编码自动建议。我了解 API 的工作原理,它是我寻求指导的 Flutter 中的实现。

以前版本有一个 Javascript 示例

    https://developer.here.com/documentation/examples/rest/geocoding_suggestions 

这演示了调用和 Json 返回,但我想知道在显示数据时是否有任何关于实现的 Flutter 示例/指导。

例如,API 返回 'London' 的地址结果,Flutter 是否具有向用户显示这些结果的内置功能(例如 TypeAheadField),例如在输入字段下方的下拉样式框中,例如下面的 HERE 屏幕截图,其中用户可以选择正确的建议吗?这个函数如何实现调用?

我想我将使用onChanged/SetState 风格的函数来调用和显示,但它是如何将调用作为用户类型然后显示返回的suggestion,我会发现一个有用的示例。

欢迎任何资源/提示

谢谢

【问题讨论】:

    标签: flutter dart here-api


    【解决方案1】:

    请检查下面的代码,它解释了在颤振中使用自动建议。

    import 'dart:typed_data';
    
    import 'package:flutter/services.dart';
    import 'package:here_sdk/core.dart';
    import 'package:here_sdk/core.errors.dart';
    import 'package:here_sdk/gestures.dart';
    import 'package:here_sdk/mapview.dart';
    import 'package:here_sdk/search.dart';
    
    import 'SearchResultMetadata.dart';
    
    // A callback to notify the hosting widget.
    typedef ShowDialogFunction = void Function(String title, String message);
    
    class SearchExample {
      HereMapController _hereMapController;
      MapCamera _camera;
      MapImage? _poiMapImage;
      List<MapMarker> _mapMarkerList = [];
      late SearchEngine _onlineSearchEngine;
      late OfflineSearchEngine _offlineSearchEngine;
      bool useOnlineSearchEngine = true;
      ShowDialogFunction _showDialog;
    
      SearchExample(ShowDialogFunction showDialogCallback, HereMapController hereMapController)
          : _showDialog = showDialogCallback,
            _hereMapController = hereMapController,
            _camera = hereMapController.camera {
        double distanceToEarthInMeters = 5000;
        MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters);
        _camera.lookAtPointWithMeasure(GeoCoordinates(52.520798, 13.409408), mapMeasureZoom);
    
        try {
          _onlineSearchEngine = SearchEngine();
        } on InstantiationException {
          throw ("Initialization of SearchEngine failed.");
        }
    
        try {
          // Allows to search on already downloaded or cached map data.
          _offlineSearchEngine = OfflineSearchEngine();
        } on InstantiationException {
          throw ("Initialization of OfflineSearchEngine failed.");
        }
    
        _setTapGestureHandler();
        _setLongPressGestureHandler();
    
        _showDialog("Note", "Long press on the map to get the address for that location with reverse geocoding.");
      }
    
      Future<void> searchButtonClicked() async {
        // Search for "Pizza" and show the results on the map.
        _searchExample();
    
        // Search for auto suggestions and log the results to the console.
        _autoSuggestExample();
      }
    
      Future<void> geocodeAnAddressButtonClicked() async {
        // Search for the location that belongs to an address and show it on the map.
        _geocodeAnAddress();
      }
    
      void useOnlineSearchEngineButtonClicked() {
        useOnlineSearchEngine = true;
    
        _showDialog('Switched to SearchEngine', 'Requests will be calculated online.');
      }
    
      void useOfflineSearchEngineButtonClicked() {
        useOnlineSearchEngine = false;
    
        // Note that this app does not show how to download offline maps. For this, check the offline_maps_app example.
        _showDialog(
            'Switched to OfflineSearchEngine', 'Requests will be calculated offline on cached or downloaded map data.');
      }
    
      void _searchExample() {
        String searchTerm = "Pizza";
        print("Searching in viewport for: " + searchTerm);
        _searchInViewport(searchTerm);
      }
    
      void _geocodeAnAddress() {
        // Set map to expected location.
        GeoCoordinates geoCoordinates = GeoCoordinates(52.53086, 13.38469);
        double distanceToEarthInMeters = 1000 * 5;
        MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters);
        _camera.lookAtPointWithMeasure(geoCoordinates, mapMeasureZoom);
    
        String queryString = "Invalidenstraße 116, Berlin";
    
        print("Finding locations for: $queryString. Tap marker to see the coordinates.");
    
        _geocodeAddressAtLocation(queryString, geoCoordinates);
      }
    
      void _setTapGestureHandler() {
        _hereMapController.gestures.tapListener = TapListener((Point2D touchPoint) {
          _pickMapMarker(touchPoint);
        });
      }
    
      void _setLongPressGestureHandler() {
        _hereMapController.gestures.longPressListener = LongPressListener((GestureState gestureState, Point2D touchPoint) {
          if (gestureState == GestureState.begin) {
            GeoCoordinates? geoCoordinates = _hereMapController.viewToGeoCoordinates(touchPoint);
            if (geoCoordinates == null) {
              return;
            }
            _addPoiMapMarker(geoCoordinates);
            _getAddressForCoordinates(geoCoordinates);
          }
        });
      }
    
      Future<void> _getAddressForCoordinates(GeoCoordinates geoCoordinates) async {
        SearchOptions reverseGeocodingOptions = SearchOptions.withDefaults();
        reverseGeocodingOptions.languageCode = LanguageCode.enGb;
        reverseGeocodingOptions.maxItems = 1;
    
        if (useOnlineSearchEngine) {
          _onlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
              (SearchError? searchError, List<Place>? list) async {
            _handleReverseGeocodingResults(searchError, list);
          });
        } else {
          _offlineSearchEngine.searchByCoordinates(geoCoordinates, reverseGeocodingOptions,
              (SearchError? searchError, List<Place>? list) async {
            _handleReverseGeocodingResults(searchError, list);
          });
        }
      }
    
      // Note that this can be called by the online or offline search engine.
      void _handleReverseGeocodingResults(SearchError? searchError, List<Place>? list) {
        if (searchError != null) {
          _showDialog("Reverse geocoding", "Error: " + searchError.toString());
          return;
        }
    
        // If error is null, list is guaranteed to be not empty.
        _showDialog("Reverse geocoded address:", list!.first.address.addressText);
      }
    
      void _pickMapMarker(Point2D touchPoint) {
        double radiusInPixel = 2;
        _hereMapController.pickMapItems(touchPoint, radiusInPixel, (pickMapItemsResult) {
          if (pickMapItemsResult == null) {
            // Pick operation failed.
            return;
          }
          List<MapMarker>? mapMarkerList = pickMapItemsResult.markers;
          if (mapMarkerList.length == 0) {
            print("No map markers found.");
            return;
          }
    
          MapMarker topmostMapMarker = mapMarkerList.first;
          Metadata? metadata = topmostMapMarker.metadata;
          if (metadata != null) {
            CustomMetadataValue? customMetadataValue = metadata.getCustomValue("key_search_result");
            if (customMetadataValue != null) {
              SearchResultMetadata searchResultMetadata = customMetadataValue as SearchResultMetadata;
              String title = searchResultMetadata.searchResult.title;
              String vicinity = searchResultMetadata.searchResult.address.addressText;
              _showDialog("Picked Search Result", title + ". Vicinity: " + vicinity);
              return;
            }
          }
    
          double lat = topmostMapMarker.coordinates.latitude;
          double lon = topmostMapMarker.coordinates.longitude;
          _showDialog("Picked Map Marker", "Geographic coordinates: $lat, $lon.");
        });
      }
    
      Future<void> _searchInViewport(String queryString) async {
        _clearMap();
    
        GeoBox viewportGeoBox = _getMapViewGeoBox();
        TextQueryArea queryArea = TextQueryArea.withBox(viewportGeoBox);
        TextQuery query = TextQuery.withArea(queryString, queryArea);
    
        SearchOptions searchOptions = SearchOptions.withDefaults();
        searchOptions.languageCode = LanguageCode.enUs;
        searchOptions.maxItems = 30;
    
        if (useOnlineSearchEngine) {
          _onlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
            _handleSearchResults(searchError, list, queryString);
          });
        } else {
          _offlineSearchEngine.searchByText(query, searchOptions, (SearchError? searchError, List<Place>? list) async {
            _handleSearchResults(searchError, list, queryString);
          });
        }
      }
    
      // Note that this can be called by the online or offline search engine.
      void _handleSearchResults(SearchError? searchError, List<Place>? list, String queryString) {
        if (searchError != null) {
          // Note: When using the OfflineSearchEngine, the HERE SDK searches only on cached map data and
          // search results may not be available for all zoom levels.
          // Please also note that it may take time until the required map data is loaded.
          // Subsequently, the cache is filled when a user pans and zooms the map.
          _showDialog("Search", "Error: " + searchError.toString());
          return;
        }
    
        // If error is null, list is guaranteed to be not empty.
        int listLength = list!.length;
        _showDialog("Search for $queryString", "Results: $listLength. Tap marker to see details.");
    
        // Add new marker for each search result on map.
        for (Place searchResult in list) {
          Metadata metadata = Metadata();
          metadata.setCustomValue("key_search_result", SearchResultMetadata(searchResult));
          // Note: getGeoCoordinates() may return null only for Suggestions.
          _addPoiMapMarkerWithMetadata(searchResult.geoCoordinates!, metadata);
        }
      }
    
      Future<void> _autoSuggestExample() async {
        GeoCoordinates centerGeoCoordinates = _getMapViewCenter();
    
        SearchOptions searchOptions = SearchOptions.withDefaults();
        searchOptions.languageCode = LanguageCode.enUs;
        searchOptions.maxItems = 5;
    
        TextQueryArea queryArea = TextQueryArea.withCenter(centerGeoCoordinates);
    
        if (useOnlineSearchEngine) {
          // Simulate a user typing a search term.
          _onlineSearchEngine.suggest(
              TextQuery.withArea(
                  "p", // User typed "p".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
    
          _onlineSearchEngine.suggest(
              TextQuery.withArea(
                  "pi", // User typed "pi".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
    
          _onlineSearchEngine.suggest(
              TextQuery.withArea(
                  "piz", // User typed "piz".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
        } else {
          // Simulate a user typing a search term.
          _offlineSearchEngine.suggest(
              TextQuery.withArea(
                  "p", // User typed "p".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
    
          _offlineSearchEngine.suggest(
              TextQuery.withArea(
                  "pi", // User typed "pi".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
    
          _offlineSearchEngine.suggest(
              TextQuery.withArea(
                  "piz", // User typed "piz".
                  queryArea),
              searchOptions, (SearchError? searchError, List<Suggestion>? list) async {
            _handleSuggestionResults(searchError, list);
          });
        }
      }
    
      void _handleSuggestionResults(SearchError? searchError, List<Suggestion>? list) {
        if (searchError != null) {
          print("Autosuggest Error: " + searchError.toString());
          return;
        }
    
        // If error is null, list is guaranteed to be not empty.
        int listLength = list!.length;
        print("Autosuggest results: $listLength.");
    
        for (Suggestion autosuggestResult in list) {
          String addressText = "Not a place.";
          Place? place = autosuggestResult.place;
          if (place != null) {
            addressText = place.address.addressText;
          }
    
          print("Autosuggest result: " + autosuggestResult.title + " addressText: " + addressText);
        }
      }
    
      Future<void> _geocodeAddressAtLocation(String queryString, GeoCoordinates geoCoordinates) async {
        _clearMap();
    
        AddressQuery query = AddressQuery.withAreaCenter(queryString, geoCoordinates);
    
        SearchOptions geocodingOptions = SearchOptions.withDefaults();
        geocodingOptions.languageCode = LanguageCode.deDe;
        geocodingOptions.maxItems = 30;
    
        if (useOnlineSearchEngine) {
          _onlineSearchEngine.searchByAddress(query, geocodingOptions, (SearchError? searchError, List<Place>? list) async {
            _handleGeocodingResults(searchError, list, queryString);
          });
        } else {
          _offlineSearchEngine.searchByAddress(query, geocodingOptions,
              (SearchError? searchError, List<Place>? list) async {
            _handleGeocodingResults(searchError, list, queryString);
          });
        }
      }
    
      // Note that this can be called by the online or offline search engine.
      void _handleGeocodingResults(SearchError? searchError, List<Place>? list, String queryString) {
        if (searchError != null) {
          _showDialog("Geocoding", "Error: " + searchError.toString());
          return;
        }
    
        String locationDetails = "";
    
        // If error is null, list is guaranteed to be not empty.
        for (Place geocodingResult in list!) {
          // Note: getGeoCoordinates() may return null only for Suggestions.
          GeoCoordinates geoCoordinates = geocodingResult.geoCoordinates!;
          Address address = geocodingResult.address;
          locationDetails = address.addressText +
              ". GeoCoordinates: " +
              geoCoordinates.latitude.toString() +
              ", " +
              geoCoordinates.longitude.toString();
    
          print("GeocodingResult: " + locationDetails);
          _addPoiMapMarker(geoCoordinates);
        }
    
        int itemsCount = list.length;
        _showDialog("Geocoding result for $queryString. Results: $itemsCount", locationDetails);
      }
    
      Future<MapMarker> _addPoiMapMarker(GeoCoordinates geoCoordinates) async {
        // Reuse existing MapImage for new map markers.
        if (_poiMapImage == null) {
          Uint8List imagePixelData = await _loadFileAsUint8List('poi.png');
          _poiMapImage = MapImage.withPixelDataAndImageFormat(imagePixelData, ImageFormat.png);
        }
    
        MapMarker mapMarker = MapMarker(geoCoordinates, _poiMapImage!);
        _hereMapController.mapScene.addMapMarker(mapMarker);
        _mapMarkerList.add(mapMarker);
    
        return mapMarker;
      }
    
      Future<Uint8List> _loadFileAsUint8List(String fileName) async {
        // The path refers to the assets directory as specified in pubspec.yaml.
        ByteData fileData = await rootBundle.load('assets/' + fileName);
        return Uint8List.view(fileData.buffer);
      }
    
      Future<void> _addPoiMapMarkerWithMetadata(GeoCoordinates geoCoordinates, Metadata metadata) async {
        MapMarker mapMarker = await _addPoiMapMarker(geoCoordinates);
        mapMarker.metadata = metadata;
      }
    
      GeoCoordinates _getMapViewCenter() {
        return _camera.state.targetCoordinates;
      }
    
      GeoBox _getMapViewGeoBox() {
        GeoBox? geoBox = _camera.boundingBox;
        if (geoBox == null) {
          print(
              "GeoBox creation failed, corners are null. This can happen when the map is tilted. Falling back to a fixed box.");
          GeoCoordinates southWestCorner = GeoCoordinates(
              _camera.state.targetCoordinates.latitude - 0.05, _camera.state.targetCoordinates.longitude - 0.05);
          GeoCoordinates northEastCorner = GeoCoordinates(
              _camera.state.targetCoordinates.latitude + 0.05, _camera.state.targetCoordinates.longitude + 0.05);
          geoBox = GeoBox(southWestCorner, northEastCorner);
        }
        return geoBox;
      }
    
      void _clearMap() {
        _mapMarkerList.forEach((mapMarker) {
          _hereMapController.mapScene.removeMapMarker(mapMarker);
        });
        _mapMarkerList.clear();
      }
    }

    更多详情请查看enter link description here

    【讨论】:

      猜你喜欢
      • 2019-06-02
      • 1970-01-01
      • 2013-05-07
      • 2021-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多