我需要使用google placeAutocomplete小部件在下拉列表中显示地点列表.在这里,我正在根据我的查询来显示场所的对话框,但是我需要为Uber,Ola应用程序中的搜索结果对话框定制设计.在这里我想要像下面的图像的设计.如果有人这样做,请给我你的建议,谢谢提前.
解决方法
您需要自定义适配器.我在我的项目中实现了这个功能.你可以按照这个.
activity_search.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@color/white"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/search_layout" android:layout_width="match_parent" android:layout_height="50dp" android:gravity="center_vertical" android:layout_alignParentTop="true" android:background="@drawable/searchbar_bg" android:layout_marginLeft="@dimen/activity_margin_10" android:layout_marginRight="@dimen/activity_margin_10" android:layout_marginTop="@dimen/activity_margin_10" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/search_et" android:layout_width="match_parent" android:layout_height="match_parent" android:hint="Search" android:singleLine="true" android:layout_toLeftOf="@+id/clear" android:imeOptions="actionSearch" android:background="@null" android:drawableLeft="@drawable/ic_action_search" android:drawablePadding="@dimen/activity_margin_10" android:paddingLeft="@dimen/activity_margin_10" android:paddingRight="@dimen/activity_margin_10"/> <ImageView android:id="@+id/clear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_clear" android:layout_alignParentRight="true" android:layout_gravity="right|center_vertical" android:padding="@dimen/activity_margin_16" android:visibility="gone"/> </RelativeLayout> </LinearLayout> <android.support.v7.widget.RecyclerView android:id="@+id/list_search" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/search_layout" android:layout_above="@+id/powered_by_google" android:background="@color/white" android:layout_marginTop="@dimen/activity_margin_10"/> <ImageView android:id="@+id/powered_by_google" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:padding="@dimen/activity_margin_10" android:layout_marginBottom="@dimen/activity_margin_10" android:src="@drawable/powered_by_google_light"/> </RelativeLayout> </LinearLayout>
SearchActivity.java
package com.android.dezi.views.rider.Activities; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; import com.android.dezi.BaseActivity; import com.android.dezi.R; import com.android.dezi.adapters.PlaceAutocompleteAdapter; import com.android.dezi.adapters.PlaceAutocompleteAdapter.PlaceAutoCompleteInterface; import com.android.dezi.adapters.PlaceSavedAdapter; import com.android.dezi.adapters.PlaceSavedAdapter.SavedPlaceListener; import com.android.dezi.beans.SavedAddress; import com.android.dezi.views.rider.Fragments.SearchFragment; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.ResultCallback; import com.google.android.gms.location.LocationServices; import com.google.android.gms.location.places.Place; import com.google.android.gms.location.places.PlaceBuffer; import com.google.android.gms.location.places.Places; import com.google.android.gms.location.places.ui.PlaceAutocomplete; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import java.util.ArrayList; import java.util.List; /** * Created by anuj.sharma on 4/6/2016. */ public class SearchActivity extends BaseActivity implements PlaceAutoCompleteInterface,GoogleApiClient.OnConnectionFailedListener,GoogleApiClient.ConnectionCallbacks,OnClickListener,SavedPlaceListener { Context mContext; GoogleApiClient mGoogleApiClient; LinearLayout mParent; private RecyclerView mRecyclerView; LinearLayoutManager llm; PlaceAutocompleteAdapter mAdapter; List<SavedAddress> mSavedAddressList; PlaceSavedAdapter mSavedAdapter; private static final LatLngBounds BOUNDS_INDIA = new LatLngBounds( new LatLng(-0,0),new LatLng(0,0)); EditText mSearchEdittext; ImageView mClear; @Override public void onStart() { mGoogleApiClient.connect(); super.onStart(); } @Override public void onStop() { mGoogleApiClient.disconnect(); super.onStop(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_search); mContext = SearchActivity.this; mGoogleApiClient = new GoogleApiClient.Builder(this) .enableAutoManage(this,0 /* clientId */,this) .addApi(Places.GEO_DATA_API) .build(); initViews(); } /* Initialize Views */ private void initViews(){ mRecyclerView = (RecyclerView)findViewById(R.id.list_search); mRecyclerView.setHasFixedSize(true); llm = new LinearLayoutManager(mContext); mRecyclerView.setLayoutManager(llm); mSearchEdittext = (EditText)findViewById(R.id.search_et); mClear = (ImageView)findViewById(R.id.clear); mClear.setOnClickListener(this); mAdapter = new PlaceAutocompleteAdapter(this,R.layout.view_placesearch,mGoogleApiClient,BOUNDS_INDIA,null); mRecyclerView.setAdapter(mAdapter); mSearchEdittext.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s,int start,int count,int after) { } @Override public void onTextChanged(CharSequence s,int before,int count) { if (count > 0) { mClear.setVisibility(View.VISIBLE); if (mAdapter != null) { mRecyclerView.setAdapter(mAdapter); } } else { mClear.setVisibility(View.GONE); if (mSavedAdapter != null && mSavedAddressList.size() > 0) { mRecyclerView.setAdapter(mSavedAdapter); } } if (!s.toString().equals("") && mGoogleApiClient.isConnected()) { mAdapter.getFilter().filter(s.toString()); } else if (!mGoogleApiClient.isConnected()) { // Toast.makeText(getApplicationContext(),Constants.API_NOT_CONNECTED,Toast.LENGTH_SHORT).show(); Log.e("","NOT CONNECTED"); } } @Override public void afterTextChanged(Editable s) { } }); } @Override public void onClick(View v) { if(v == mClear){ mSearchEdittext.setText(""); if(mAdapter!=null){ mAdapter.clearList(); } } } @Override public void onConnected(Bundle bundle) { } @Override public void onConnectionSuspended(int i) { } @Override public void onConnectionFailed(ConnectionResult connectionResult) { } @Override public void onPlaceClick(ArrayList<PlaceAutocompleteAdapter.PlaceAutocomplete> mResultList,int position) { if(mResultList!=null){ try { final String placeId = String.valueOf(mResultList.get(position).placeId); /* Issue a request to the Places Geo Data API to retrieve a Place object with additional details about the place. */ PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi .getPlaceById(mGoogleApiClient,placeId); placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() { @Override public void onResult(PlaceBuffer places) { if(places.getCount()==1){ //Do the things here on Click..... Intent data = new Intent(); data.putExtra("lat",String.valueOf(places.get(0).getLatLng().latitude)); data.putExtra("lng",String.valueOf(places.get(0).getLatLng().longitude)); setResult(SearchActivity.RESULT_OK,data); finish(); }else { Toast.makeText(getApplicationContext(),"something went wrong",Toast.LENGTH_SHORT).show(); } } }); } catch (Exception e){ } } } @Override public void onSavedPlaceClick(List<SavedAddress> mResponse,int position) { if(mResponse!=null){ try { Intent data = new Intent(); data.putExtra("lat",String.valueOf(mResponse.get(position).getLatitude())); data.putExtra("lng",String.valueOf(mResponse.get(position).getLongitude())); setResult(SearchActivity.RESULT_OK,data); finish(); } catch (Exception e){ } } } }
PlaceAutocompleteAdapter.java
这是定制的适配器.所有重要的部分都在这里.
package com.android.dezi.adapters; import android.content.Context; import android.graphics.Typeface; import android.support.v7.widget.RecyclerView; import android.text.style.CharacterStyle; import android.text.style.StyleSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Filter; import android.widget.Filterable; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.android.dezi.R; import com.android.dezi.beans.TripHistoryBean; import com.android.dezi.views.rider.Fragments.SearchFragment; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.common.api.PendingResult; import com.google.android.gms.common.api.Status; import com.google.android.gms.common.data.DataBufferUtils; import com.google.android.gms.location.places.AutocompleteFilter; import com.google.android.gms.location.places.AutocompletePrediction; import com.google.android.gms.location.places.AutocompletePredictionBuffer; import com.google.android.gms.location.places.Places; import com.google.android.gms.maps.model.LatLngBounds; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; /** * Created by anuj.sharma on 4/6/2016. */ public class PlaceAutocompleteAdapter extends RecyclerView.Adapter<PlaceAutocompleteAdapter.PlaceViewHolder> implements Filterable{ public interface PlaceAutoCompleteInterface{ public void onPlaceClick(ArrayList<PlaceAutocomplete> mResultList,int position); } Context mContext; PlaceAutoCompleteInterface mListener; private static final String TAG = "PlaceAutocompleteAdapter"; private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD); ArrayList<PlaceAutocomplete> mResultList; private GoogleApiClient mGoogleApiClient; private LatLngBounds mBounds; private int layout; private AutocompleteFilter mPlaceFilter; public PlaceAutocompleteAdapter(Context context,int resource,GoogleApiClient googleApiClient,LatLngBounds bounds,AutocompleteFilter filter){ this.mContext = context; layout = resource; mGoogleApiClient = googleApiClient; mBounds = bounds; mPlaceFilter = filter; this.mListener = (PlaceAutoCompleteInterface)mContext; } /* Clear List items */ public void clearList(){ if(mResultList!=null && mResultList.size()>0){ mResultList.clear(); } } /** * Sets the bounds for all subsequent queries. */ public void setBounds(LatLngBounds bounds) { mBounds = bounds; } @Override public Filter getFilter() { Filter filter = new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); // Skip the autocomplete query if no constraints are given. if (constraint != null) { // Query the autocomplete API for the (constraint) search string. mResultList = getAutocomplete(constraint); if (mResultList != null) { // The API successfully returned results. results.values = mResultList; results.count = mResultList.size(); } } 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. notifyDataSetChanged(); } else { // The API did not return any results,invalidate the data set. //notifyDataSetInvalidated(); } } }; return filter; } private ArrayList<PlaceAutocomplete> getAutocomplete(CharSequence constraint) { if (mGoogleApiClient.isConnected()) { Log.i("","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(mContext,"Error contacting API: " + status.toString(),// Toast.LENGTH_SHORT).show(); Log.e("","Error getting autocomplete prediction API call: " + status.toString()); autocompletePredictions.release(); return null; } Log.i("","Query completed. Received " + autocompletePredictions.getCount() + " predictions."); // Copy the results into our own data structure,because we can't hold onto the buffer. // AutocompletePrediction objects encapsulate the API response (place ID and description). Iterator<AutocompletePrediction> iterator = autocompletePredictions.iterator(); ArrayList resultList = new ArrayList<>(autocompletePredictions.getCount()); while (iterator.hasNext()) { AutocompletePrediction prediction = iterator.next(); // Get the details of this prediction and copy it into a new PlaceAutocomplete object. resultList.add(new PlaceAutocomplete(prediction.getPlaceId(),prediction.getDescription())); } // Release the buffer now that all data has been copied. autocompletePredictions.release(); return resultList; } Log.e("","Google API client is not connected for autocomplete query."); return null; } @Override public PlaceViewHolder onCreateViewHolder(ViewGroup viewGroup,int viewType) { LayoutInflater layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View convertView = layoutInflater.inflate(layout,viewGroup,false); PlaceViewHolder mPredictionHolder = new PlaceViewHolder(convertView); return mPredictionHolder; } @Override public void onBindViewHolder(PlaceViewHolder mPredictionHolder,final int i) { mPredictionHolder.mAddress.setText(mResultList.get(i).description); mPredictionHolder.mParentLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mListener.onPlaceClick(mResultList,i); } }); } @Override public int getItemCount() { if(mResultList != null) return mResultList.size(); else return 0; } public PlaceAutocomplete getItem(int position) { return mResultList.get(position); } /* View Holder For Trip History */ public class PlaceViewHolder extends RecyclerView.ViewHolder { // CardView mCardView; public RelativeLayout mParentLayout; public TextView mAddress; public PlaceViewHolder(View itemView) { super(itemView); mParentLayout = (RelativeLayout)itemView.findViewById(R.id.predictedRow); mAddress = (TextView)itemView.findViewById(R.id.address); } } /** * Holder for Places Geo Data Autocomplete API results. */ public class PlaceAutocomplete { public CharSequence placeId; public CharSequence description; PlaceAutocomplete(CharSequence placeId,CharSequence description) { this.placeId = placeId; this.description = description; } @Override public String toString() { return description.toString(); } } }
view_placesearch.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/predictedRow" android:layout_width="match_parent" android:layout_height="65dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_centerVertical="true" android:gravity="center_vertical"> <ImageView android:id="@+id/image" android:layout_width="22dp" android:layout_height="22dp" android:src="@drawable/ic_action_navigate" android:layout_marginLeft="10dp" android:layout_marginTop="20dp" /> <TextView android:id="@+id/address" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#000" android:textSize="15sp" android:layout_toRightOf="@+id/image" android:layout_centerVertical="true" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/light_gray" android:layout_alignParentBottom="true"/> </RelativeLayout>
希望它也会帮助你.
输出将如下:
我找到一些有用的链接,也可以帮助你.