2017-08-17 10 views
-1

Xamarinフォームマップでカスタム検索バーにオートコンプリートサービスを追加しようとしていますが(私はエントリを使用しています)、これはできませんでした。Xamarin google maps autocomplete

私はすでにXLabsで試してみましたが、うまくいきませんでした。これまで他の解決策は見つかりませんでした。

Xamarin.FormsMapsにはオートコンプリート機能が含まれていますか?または、既にXamarinに自動補完機能がありますか? 私に何をお勧めしますか?コードなどが必要な場合は、教えてください。

+0

hvaughan3 @ [Xamarin.FormsでGoogleの場所オートコンプリート](https://stackoverflow.com/questions/34390423/google-place-autocomplete-in-xamarin-forms) – hvaughan3

+0

の可能性の重複私はすでに、1ことを見ましたそれはアンドロイド独占だから、その質問については何の答えもチェックされていない。ありがとうtho。 –

答えて

1

これは長いものですが、ここには....サービス呼び出しコードをサービスclassに入れ、他のコードをすべてViewModelに入れたいと思います。また、サービスコールメソッド内またはその周辺で、nullとエラーチェックを追加することもできます。

重要な点の1つは、検索の実行中にGoogleロゴが表示されるというGoogleの要件です。したがって、their iconをダウンロードしてUIに追加してください。ユーザーがEntryにフォーカスしているときにのみ表示します。

したがって、これらは、場所のモデルであり、私自身のAddressモデル:

public class AddressInfo { 

    public string Address { get; set; } 

    public string City { get; set; } 

    public string State { get; set; } 

    public string ZipCode { get; set; } 

    public double Longitude { get; set; } 

    public double Latitude { get; set; } 
} 

public class PlacesMatchedSubstring { 

    [Newtonsoft.Json.JsonProperty("length")] 
    public int Length { get; set; } 

    [Newtonsoft.Json.JsonProperty("offset")] 
    public int Offset { get; set; } 
} 

public class PlacesTerm { 

    [Newtonsoft.Json.JsonProperty("offset")] 
    public int Offset { get; set; } 

    [Newtonsoft.Json.JsonProperty("value")] 
    public string Value { get; set; } 
} 

public class Prediction { 

    [Newtonsoft.Json.JsonProperty("id")] 
    public string Id { get; set; } 

    [Newtonsoft.Json.JsonProperty("description")] 
    public string Description { get; set; } 

    [Newtonsoft.Json.JsonProperty("matched_substrings")] 
    public List<PlacesMatchedSubstring> MatchedSubstrings { get; set; } 

    [Newtonsoft.Json.JsonProperty("place_id")] 
    public string PlaceId { get; set; } 

    [Newtonsoft.Json.JsonProperty("reference")] 
    public string Reference { get; set; } 

    [Newtonsoft.Json.JsonProperty("terms")] 
    public List<PlacesTerm> Terms { get; set; } 

    [Newtonsoft.Json.JsonProperty("types")] 
    public List<string> Types { get; set; } 
} 

public class PlacesLocationPredictions { 

    [Newtonsoft.Json.JsonProperty("predictions")] 
    public List<Prediction> Predictions { get; set; } 

    [Newtonsoft.Json.JsonProperty("status")] 
    public string Status { get; set; } 
} 

ここでは、場所APIを呼び出す:

UIのための今
public const string GooglePlacesApiAutoCompletePath = "https://maps.googleapis.com/maps/api/place/autocomplete/json?key={0}&input={1}&components=country:us"; //Adding country:us limits results to us 

public const string GooglePlacesApiKey = "bTafrOPmO4LpPgAl34r5wQ6LFRWhgTxBW80-3GK"; 

private static HttpClient _httpClientInstance; 
public static HttpClient HttpClientInstance => _httpClientInstance ?? (_httpClientInstance = new HttpClient()); 

private ObservableCollection<AddressInfo> _addresses; 
public ObservableCollection<AddressInfo> Addresses { 
    get => _addresses ?? (_addresses = new ObservableCollection<AddressInfo>()); 
    set { 
     if(_addresses != value) { 
      _addresses = value; 
      OnPropertyChanged(); 
     } 
    }; 
} 

private string _addressText; 
public string AddressText { 
    get => _addressText; 
    set { 
     if(_addressText != value) { 
      _addressText = value; 
      OnPropertyChanged(); 
     } 
    }; 
} 

public async Task GetPlacesPredictionsAsync() { 

    // TODO: Add throttle logic, Google begins denying requests if too many are made in a short amount of time 

    CancellationToken cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token; 

    using(HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, string.Format(GooglePlacesApiAutoCompletePath, ConstantKeys.GooglePlacesApiKey, WebUtility.UrlEncode(_addressText)))) { //Be sure to UrlEncode the search term they enter 

     using(HttpResponseMessage message = await HttpClientInstance.SendAsync(request, HttpCompletionOption.ResponseContentRead, cancellationToken).ConfigureAwait(false)) { 
      if(message.IsSuccessStatusCode) { 
       string json = await message.Content.ReadAsStringAsync().ConfigureAwait(false); 

       PlacesLocationPredictions predictionList = await Task.Run(() => JsonConvert.DeserializeObject<PlacesLocationPredictions>(json)).ConfigureAwait(false); 

       if(predictionList.Status == "OK") { 

        Addresses.Clear(); 

        if(predictionList.Predictions.Count > 0) { 
         foreach(Prediction prediction in predictionList.Predictions) { 
          Addresses.Add(new AddressInfo { 
           Address = prediction.Description 
          }); 
         } 
        } 
       } else { 
        throw new Exception(predictionList.Status); 
       } 
      } 
     } 
    } 
} 

...

<Entry Text="{Binding AddressText}" 
      TextChanged="OnTextChanged" /> 

    <ListView ItemsSource="{Binding Addresses}"> 
     <ListView.ItemTemplate> 
     <DataTemplate> 
      <TextCell Text="{Binding Address}"/> 
     </DataTemplate>Text 
     </ListView.ItemTemplate> 
    </ListView> 

コードの後ろ:

private async void OnTextChanged(object sender, EventArgs eventArgs) { 
    if(!string.IsNullOrWhiteSpace(ViewModel.AddressText)) { 
     await ViewModel.GetPlacesPredictionsAsync(); 
    } 
} 
+0

それはまさに私が必要としていたことです。もし私が尋ねることができるなら、どのように座標を取得しますか?ジオコーダーを使用していますか? –

+0

@MauricioCárdenas 'Prediction'クラスの座標ですか?もしそうなら、はい。私はGoogle Geocode APIを使用しています。サービスコールにジオコードURLを使用し、レスポンスを異なるモデルに逆シリアル化する点を除いて、ほとんど同じコードです。 – hvaughan3

+0

@ hvaughan3はこの行です:ViewModel.GetAddressCoordinatesAsync();を待ちます。 GetPlacesPredictionsAsyncを呼び出す必要がありますか? –

関連する問題