与Uber一样,ListView中显示的带有Google Places的AutoCompleteTextView

我需要制作类似于此的屏幕。 我认为它有autocompletetextview和listview来显示返回的结果。 谷歌的地方API用于这里自动build议的地方和列表视图适配器相应地更新。 请任何forms的帮助表示赞赏。 提前致谢。

在AutoComplete上也检查了android示例项目。 但它没有任何listview来显示结果。 而是在autocompletetextview微调器中显示结果。 任何修改,我们可以做这个项目

链接到谷歌示例项目

Uber PickUp位置屏幕

Solutions Collecting From Web of "与Uber一样,ListView中显示的带有Google Places的AutoCompleteTextView"

您可以通过使用EditTextListView ,而不是AutoCompleteTextView完全实现此目的。 在EditText中input字符,通过调用GooglePlacesAutomplete webservice来过滤ListView中的结果。 以下是代码:

这是你的layoout文件(带有ListView EditText

 <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并应用Filterable。 你必须使用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()应用于相应ActivityEditText 。 以下内容将添加到与之前创build的布局相对应的“活动”中:

 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

您可以通过将下面的代码添加到布局中,以更简单的方式实现自动完成的textview

 <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" /> 

要使用上述代码,您需要在Google develepor控制台中为您的应用程序configuration一些设置。请参阅Android Places自动完成示例以获取完整的示例

这是一个如何做到这一点的例子。

您有从适配器获取任何AutocompletePrediction的奖金。 只需从AutoCompleteTextViewAdapterView.OnItemClickListener调用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; } }