8

Tôi cần tạo màn hình tương tự như vậy. Tôi nghĩ rằng nó có autocompletetextview và listview để hiển thị kết quả trả về. API Google Place được sử dụng ở đây để tự động đề xuất địa điểm và bộ điều hợp danh sách xem được cập nhật tương ứng. Xin vui lòng bất kỳ loại trợ giúp được đánh giá cao. Cảm ơn trước.AutoCompleteTextView với Google Địa điểm được hiển thị trong ListView giống như Uber

Đã kiểm tra dự án mẫu Android trên Tự động điền cho các địa điểm. Nhưng nó không có bất kỳ listview để hiển thị kết quả. Thay vào đó, nó cho thấy kết quả trong spinner tự động hoàn thành. Bất kỳ sửa đổi chúng ta có thể làm gì với dự án mà

Link to google sample project

Uber PickUp location screen

+1

thử liên kết này http://wptrafficanalyzer.in/blog/android-autocompletetextview-with-google-places-autocomplete-api/ –

+0

cũng gửi mã của bạn để hiển thị nỗ lực của bạn –

+0

@AnjaliTripathi Cũng đã kiểm tra liên kết này. Tất cả đều hoạt động tốt.Nhưng bạn có thể thấy trình đơn thả xuống của họ để hiển thị kết quả. Tôi cần hiển thị nó trong listview giống như ảnh chụp màn hình. Cảm ơn –

Trả lời

9

Bạn có thể đạt được điều này một cách chính xác bằng cách sử dụng EditTextListView, và không AutoCompleteTextView. Các ký tự được nhập trong số EditText trên cơ sở kết quả trong số ListView được lọc bằng cách gọi số GooglePlacesAutomplete webservice. Sau đây là các mã:

Đây là tập tin của bạn layoout (EditText với ListView)

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

Trong Hoạt động tương ứng của bạn, truy cập vào EditText này và áp dụng lọc. Bạn phải sử dụng GooglePlacesAutompleteAdapter cho việc này.

Sau đây là 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; 
} 
} 

Truy cập adapter và áp dụng getFilter() đến EditText trong tương ứng Activity. Nội dung sau sẽ được thêm vào Hoạt động của bạn tương ứng với bố cục được tạo trước đó:

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()); 
     } 
    }); 

Điều này sẽ giúp bạn thực hiện. Bạn có thể sửa đổi bố cục của mình theo ý muốn. Điều này về cơ bản tải dữ liệu tự động hoàn thành trong một ListView.

+0

Tôi thích cách tiếp cận của bạn, nhưng 'saveArray' làm gì? –

+0

@SteveKamau Xin chào. Nó không liên quan đến câu trả lời này. Tôi đã lưu trữ danh sách mà tôi đã vào SharedPref bằng cách sử dụng 'saveArray'. Cảm ơn bạn đã upvote! –

1

Bạn có thể đạt TextView automcomplete theo một cách đơn giản bằng cách thêm mã dưới đây để bố trí

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

của bạn Để sử dụng đoạn mã trên bạn cần phải cấu hình vài cài đặt cho ứng dụng của bạn trong develepor console Google Xin vui lòng tham khảo Android Places autocomplete example cho ví dụ hoàn chỉnh

1

Here là ví dụ về cách thực hiện điều đó.

Bạn có tiền thưởng nhận bất kỳ số nào trong số AutocompletePrediction từ bộ điều hợp. Chỉ cần gọi getItem(int position) từ 's AdapterView.OnItemClickListener ví dụ và sử dụng bất kỳ dữ liệu nào từ dự đoán được nhấp như bạn muốn.

Liên kết mã có liên quan:

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

Đây phải là câu trả lời được chấp nhận. –

Các vấn đề liên quan