8

我需要製作類似於此的屏幕。我認爲它有autocompletetextview和listview來顯示返回的結果。 Google Place API在此用於自動建議地點,並且相應地更新listview適配器。 請任何形式的幫助表示讚賞。 在此先感謝。AutoCompleteTextView與ListView中顯示的Google Places一樣,像Uber

檢查了AutoComplete上的android示例項目。但它沒有任何列表視圖來顯示結果。相反,它會在autocompletetextview微調器中顯示結果。任何修改,我們可以準確地用EditTextListView,而不是AutoCompleteTextView與該項目

Link to google sample project

Uber PickUp location screen

+1

嘗試此鏈接http://wptrafficanalyzer.in/blog/android-autocompletetextview-with-google-places-autocomplete-api/ –

+0

還發布您的代碼,以顯示你的努力 –

+0

@AnjaliTripathi也檢查了這個鏈接。他們都運作良好。但是你可以看到他們的下拉菜單顯示結果。我需要像在屏幕截圖中一樣在listview中顯示它。謝謝 –

回答

9

你可以做到這一點做的。在EditText中輸入字符,在此基礎上通過調用GooglePlacesAutomplete web服務來過濾ListView中的結果。以下是代碼:

這是您的layoout文件(EditTextListView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:background="#ffffff" 
tools:context="com.example.siddarthshikhar.liftsharesample.EnterLocationActivity"> 

    <EditText 
     android:paddingLeft="@dimen/activity_horizontal_margin" 
     android:layout_width="250dp" 
     android:layout_height="35dp" 
     android:textColorHint="#ffffff" 
     android:id="@+id/edEnterLocation" 
     android:textColor="#ffffff" 
     android:textSize="@dimen/abc_text_size_medium_material" 
     android:layout_alignParentLeft="true" 
     android:backgroundTint="#00000000" 
     android:gravity="start|center"> 
     <requestFocus /> 
    </EditText> 

<ListView android:id="@+id/listView1" android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:layout_below="@+id/filterLayout"/> 

</RelativeLayout> 

在你相應的活動,訪問此的EditText和應用篩選。你必須爲此使用GooglePlacesAutompleteAdapter

以下是GooglePlacesAutompleteAdapter

public class GooglePlacesAutocompleteAdapter extends ArrayAdapter implements Filterable { 
private static final String LOG_TAG = "Google Places Autocomplete"; 
private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place"; 
private static final String TYPE_AUTOCOMPLETE = "/autocomplete"; 
private static final String OUT_JSON = "/json"; 
private static final String API_KEY = "your_api_key"; 
private ArrayList<String> resultList; 
private Context context = null; 
public GooglePlacesAutocompleteAdapter(Context context, int textViewResourceId) { 
    super(context, textViewResourceId); 
    this.context = context; 
} 


@Override 
public int getCount() { 
    if(resultList != null) 
     return resultList.size(); 
    else 
     return 0; 
} 

@Override 
public String getItem(int index) { 
    return resultList.get(index); 
} 


public ArrayList<String> autocomplete(String input) { 
    ArrayList<String> resultList = null; 
    ArrayList<String> descriptionList = null; 
    HttpURLConnection conn = null; 
    StringBuilder jsonResults = new StringBuilder(); 
    try { 
     StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON); 
     sb.append("?key=" + API_KEY); 
     sb.append("&components=country:in"); 
     sb.append("&input=" + URLEncoder.encode(input, "utf8")); 

     URL url = new URL(sb.toString()); 
     conn = (HttpURLConnection) url.openConnection(); 
     InputStreamReader in = new InputStreamReader(conn.getInputStream()); 

     // Load the results into a StringBuilder 
     int read; 
     char[] buff = new char[1024]; 
     while ((read = in.read(buff)) != -1) { 
      jsonResults.append(buff, 0, read); 
     } 
    } catch (MalformedURLException e) { 
     Log.e(LOG_TAG, "Error processing Places API URL", e); 
     return resultList; 
    } catch (IOException e) { 
     Log.e(LOG_TAG, "Error connecting to Places API", e); 
     return resultList; 
    } finally { 
     if (conn != null) { 
      conn.disconnect(); 
     } 
    } 

    try { 
     // Create a JSON object hierarchy from the results 
     Log.d("yo",jsonResults.toString()); 
     JSONObject jsonObj = new JSONObject(jsonResults.toString()); 
     JSONArray predsJsonArray = jsonObj.getJSONArray("predictions"); 

     // Extract the Place descriptions from the results 
     resultList = new ArrayList(predsJsonArray.length()); 
     descriptionList = new ArrayList(predsJsonArray.length()); 
     for (int i = 0; i < predsJsonArray.length(); i++) { 
      resultList.add(predsJsonArray.getJSONObject(i).toString()); 
      descriptionList.add(predsJsonArray.getJSONObject(i).getString("description")); 
     } 
     saveArray(resultList.toArray(new String[resultList.size()]), "predictionsArray", getContext()); 
    } catch (JSONException e) { 
     Log.e(LOG_TAG, "Cannot process JSON results", e); 
    } 

    return descriptionList; 
} 


@Override 
public Filter getFilter() { 
    Filter filter = new Filter() { 
     @Override 
     protected FilterResults performFiltering(CharSequence constraint) { 
      FilterResults filterResults = new FilterResults(); 
      if (constraint != null) { 
       // Retrieve the autocomplete results. 
       resultList = autocomplete(constraint.toString()); 

       // Assign the data to the FilterResults 
       filterResults.values = resultList; 
       filterResults.count = resultList.size(); 
      } 
      return filterResults; 
     } 

     @Override 
     protected void publishResults(CharSequence constraint, FilterResults results) { 
      if (results != null && results.count > 0) { 
       setImageVisibility(); 
       notifyDataSetChanged(); 
      } else { 
       notifyDataSetInvalidated(); 
      } 
     } 
    }; 
    return filter; 
} 
} 

接入適配器和適用getFilter()EditText在相應Activity。以下是你的活動添加相應前面創建您的佈局:

dataAdapter = new GooglePlacesAutocompleteAdapter(EnterLocationActivity.this, R.layout.adapter_google_places_autocomplete){ 

listView = (ListView) findViewById(R.id.listView1); 
    // Assign adapter to ListView 
    listView.setAdapter(dataAdapter); 

    //enables filtering for the contents of the given ListView 
    listView.setTextFilterEnabled(true); 

etEnterLocation.addTextChangedListener(new TextWatcher() { 

     public void afterTextChanged(Editable s) { 
     } 

     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
     } 

     public void onTextChanged(CharSequence s, int start, int before, int count) { 

      dataAdapter.getFilter().filter(s.toString()); 
     } 
    }); 

這應該讓你去。您可以根據需要修改佈局。這基本上將自動完成數據加載到ListView中。

+0

我愛你的方法,但'saveArray'做什麼? –

+0

@SteveKamau嗨。這與這個答案無關。我使用'saveArray'存儲了我進入SharedPref的列表。感謝upvote! –

1

可以通過添加下面的代碼到你的佈局

<fragment 
    android:id="@+id/place_autocomplete_fragment" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" 
/> 

對於使用你需要在谷歌develepor控制檯應用程序。請參閱Android Places autocomplete example配置一些設置上面的代碼實現了一個簡單的方法automcomplete的TextView完整的例子

1

Here是如何做到這一點的一個例子。

您可以從適配器獲得AutocompletePrediction中的任意一項獎勵。只需撥打AutoCompleteTextView的即可撥打getItem(int position),並根據需要使用預測點擊的任何數據。

鏈接相關代碼:

/** 
* Adapter that handles Autocomplete requests from the Places Geo Data API. 
* {@link AutocompletePrediction} results from the API are frozen and stored directly in this 
* adapter. (See {@link AutocompletePrediction#freeze()}.) 
* <p> 
* Note that this adapter requires a valid {@link com.google.android.gms.common.api.GoogleApiClient}. 
* The API client must be maintained in the encapsulating Activity, including all lifecycle and 
* connection states. The API client must be connected with the {@link Places#GEO_DATA_API} API. 
*/ 
public class PlaceAutocompleteAdapter 
     extends ArrayAdapter<AutocompletePrediction> implements Filterable { 

    private static final String TAG = "PlaceAutocompleteAdapter"; 
    private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD); 
    /** 
    * Current results returned by this adapter. 
    */ 
    private ArrayList<AutocompletePrediction> mResultList; 

    /** 
    * Handles autocomplete requests. 
    */ 
    private GoogleApiClient mGoogleApiClient; 

    /** 
    * The bounds used for Places Geo Data autocomplete API requests. 
    */ 
    private LatLngBounds mBounds; 

    /** 
    * The autocomplete filter used to restrict queries to a specific set of place types. 
    */ 
    private AutocompleteFilter mPlaceFilter; 

    /** 
    * Initializes with a resource for text rows and autocomplete query bounds. 
    * 
    * @see android.widget.ArrayAdapter#ArrayAdapter(android.content.Context, int) 
    */ 
    public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient, 
      LatLngBounds bounds, AutocompleteFilter filter) { 
     //change the layout nex for your own if you'd like 
     super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1); 
     mGoogleApiClient = googleApiClient; 
     mBounds = bounds; 
     mPlaceFilter = filter; 
    } 

    /** 
    * Sets the bounds for all subsequent queries. 
    */ 
    public void setBounds(LatLngBounds bounds) { 
     mBounds = bounds; 
    } 

    /** 
    * Returns the number of results received in the last autocomplete query. 
    */ 
    @Override 
    public int getCount() { 
     return mResultList.size(); 
    } 

    /** 
    * Returns an item from the last autocomplete query. 
    */ 
    @Override 
    public AutocompletePrediction getItem(int position) { 
     return mResultList.get(position); 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row = super.getView(position, convertView, parent); 

     // Sets the primary and secondary text for a row. 
     // Note that getPrimaryText() and getSecondaryText() return a CharSequence that may contain 
     // styling based on the given CharacterStyle. 

     AutocompletePrediction item = getItem(position); 

     TextView textView1 = (TextView) row.findViewById(android.R.id.text1); 
     TextView textView2 = (TextView) row.findViewById(android.R.id.text2); 
     textView1.setText(item.getPrimaryText(STYLE_BOLD)); 
     textView2.setText(item.getSecondaryText(STYLE_BOLD)); 

     return row; 
    } 

    /** 
    * Returns the filter for the current set of autocomplete results. 
    */ 
    @Override 
    public Filter getFilter() { 
     return new Filter() { 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults results = new FilterResults(); 

       // We need a separate list to store the results, since 
       // this is run asynchronously. 
       ArrayList<AutocompletePrediction> filterData = new ArrayList<>(); 

       // Skip the autocomplete query if no constraints are given. 
       if (constraint != null) { 
        // Query the autocomplete API for the (constraint) search string. 
        filterData = getAutocomplete(constraint); 
       } 

       results.values = filterData; 
       if (filterData != null) { 
        results.count = filterData.size(); 
       } else { 
        results.count = 0; 
       } 

       return results; 
      } 

      @Override 
      protected void publishResults(CharSequence constraint, FilterResults results) { 

       if (results != null && results.count > 0) { 
        // The API returned at least one result, update the data. 
        mResultList = (ArrayList<AutocompletePrediction>) results.values; 
        notifyDataSetChanged(); 
       } else { 
        // The API did not return any results, invalidate the data set. 
        notifyDataSetInvalidated(); 
       } 
      } 

      @Override 
      public CharSequence convertResultToString(Object resultValue) { 
       // Override this method to display a readable result in the AutocompleteTextView 
       // when clicked. 
       if (resultValue instanceof AutocompletePrediction) { 
        return ((AutocompletePrediction) resultValue).getFullText(null); 
       } else { 
        return super.convertResultToString(resultValue); 
       } 
      } 
     }; 
    } 

    /** 
    * Submits an autocomplete query to the Places Geo Data Autocomplete API. 
    * Results are returned as frozen AutocompletePrediction objects, ready to be cached. 
    * objects to store the Place ID and description that the API returns. 
    * Returns an empty list if no results were found. 
    * Returns null if the API client is not available or the query did not complete 
    * successfully. 
    * This method MUST be called off the main UI thread, as it will block until data is returned 
    * from the API, which may include a network request. 
    * 
    * @param constraint Autocomplete query string 
    * @return Results from the autocomplete API or null if the query was not successful. 
    * @see Places#GEO_DATA_API#getAutocomplete(CharSequence) 
    * @see AutocompletePrediction#freeze() 
    */ 
    private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) { 
     if (mGoogleApiClient.isConnected()) { 
      Log.i(TAG, "Starting autocomplete query for: " + constraint); 

      // Submit the query to the autocomplete API and retrieve a PendingResult that will 
      // contain the results when the query completes. 
      PendingResult<AutocompletePredictionBuffer> results = 
        Places.GeoDataApi 
          .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), 
            mBounds, mPlaceFilter); 

      // This method should have been called off the main UI thread. Block and wait for at most 60s 
      // for a result from the API. 
      AutocompletePredictionBuffer autocompletePredictions = results 
        .await(60, TimeUnit.SECONDS); 

      // Confirm that the query completed successfully, otherwise return null 
      final Status status = autocompletePredictions.getStatus(); 
      if (!status.isSuccess()) { 
       Toast.makeText(getContext(), "Error contacting API: " + status.toString(), 
         Toast.LENGTH_SHORT).show(); 
       Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString()); 
       autocompletePredictions.release(); 
       return null; 
      } 

      Log.i(TAG, "Query completed. Received " + autocompletePredictions.getCount() 
        + " predictions."); 

      // Freeze the results immutable representation that can be stored safely. 
      return DataBufferUtils.freezeAndClose(autocompletePredictions); 
     } 
     Log.e(TAG, "Google API client is not connected for autocomplete query."); 
     return null; 
    } 
} 
+0

這應該是一個被接受的答案。 –

相關問題