How to customize PlaceAutocomplete widget dialog design to list places

后端 未结 4 1161
刺人心
刺人心 2020-12-13 01:01

I need to show list of places in dropdown using google placeAutocomplete widgets. Here I\'m getting dialog to show places according to my query but

相关标签:
4条回答
  • 2020-12-13 01:04

    You need to customize your adapter. I had implemented this functionality in my project. You can follow this.

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

    This is customized adapter. All important part is inside this.

    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

    Customized view that you want to show in your adapter

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

    Hope it will help you too.

    Note: Do not forget to add API key in your manifest file.

    Output will be like:

    I found some Useful links that can also help you.

    1. Android Plat Places using custom Adapter

    0 讨论(0)
  • 2020-12-13 01:18

    You just need to create new arraylist every time in filter object

    @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. 
    
                   /**You just need to create new object then crash problem 
                     will not occur**/
                    mResultList = new ArrayList<>;
    
                    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;
    } 
    
    0 讨论(0)
  • 2020-12-13 01:19

    kotlin:

    fun queryPlaces(text: String) {
        val task = object : AsyncTask<Void,Void,Void>(){
            override fun doInBackground(vararg params: Void?): Void? {
                val results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, text, null, null)
                val autocompletePredictions = results.await()
                val iterator = autocompletePredictions.iterator()
                while (iterator.hasNext()) {
                    val prediction = iterator.next()
                    println("PlaceId:${prediction.placeId}")
                    println("PrimaryText:${prediction.getPrimaryText(null)}")
                }
                autocompletePredictions.release()
                return null
            }
        }
        task.execute()
    }
    

    If you want get the Place detail:

    fun queryPlaces(text: String) {
        val geoDataClient : GeoDataClient = Places.getGeoDataClient(context!!)
    
        val task = object : AsyncTask<Void,Void,Void>(){
            override fun doInBackground(vararg params: Void?): Void? {
                val results = Places.GeoDataApi.getAutocompletePredictions(mGoogleApiClient, text, null, null)
                val autocompletePredictions = results.await()
                val iterator = autocompletePredictions.iterator()
                while (iterator.hasNext()) {
                    val prediction = iterator.next()
    
                    geoDataClient.getPlaceById(prediction.placeId).addOnCompleteListener {task->
                        val places = task.result
                        val myPlace = places?.get(0)
                        println("name:${myPlace?.name}")
                        println("latLng:${myPlace?.latLng}")
                        println("address:${myPlace?.address}")
                    }
                }
                autocompletePredictions.release()
                return null
            }
        }
        task.execute()
    }
    
    0 讨论(0)
  • 2020-12-13 01:24

    In view of the latest changes in the AutocompletePrediction API, here is the revised Adapter and Filter code:

    PlaceAutoCompleteAdapter.java

    package com.equinox.prologix.Adapters;
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    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.Toast;
    
    import com.equinox.prologix.Activities.LocationChooseActivity;
    import com.equinox.prologix.Filters.PlaceAutoCompleteFilter;
    import com.equinox.prologix.R;
    import com.equinox.prologix.ViewHolders.PlaceAutoCompleteHolder;
    import com.google.android.gms.common.api.GoogleApiClient;
    import com.google.android.gms.location.places.AutocompletePrediction;
    import com.google.android.gms.location.places.GeoDataClient;
    import com.google.android.gms.location.places.Place;
    import com.google.android.gms.location.places.PlaceBufferResponse;
    import com.google.android.gms.location.places.Places;
    import com.google.android.gms.location.places.ui.PlaceAutocomplete;
    import com.google.android.gms.maps.CameraUpdateFactory;
    import com.google.android.gms.maps.GoogleMap;
    import com.google.android.gms.maps.model.LatLngBounds;
    import com.google.android.gms.tasks.OnCompleteListener;
    import com.google.android.gms.tasks.Task;
    
    import java.util.List;
    
    /**
     * Created by Mohammed Mukhtar on 12/1/2017.
     */
    
    public class PlaceAutoCompleteAdapter extends RecyclerView.Adapter<PlaceAutoCompleteHolder> implements Filterable {
    
        private Context context;
        private GoogleMap googleMap;
        private PlaceAutoCompleteFilter placeAutoCompleteFilter;
        private GeoDataClient mGeoDataClient;
        private GoogleApiClient googleApiClient;
        private Handler autoCompleteSelected;
        private List<AutocompletePrediction> resultPlaceList;
    
        public PlaceAutoCompleteAdapter(Context context, GoogleApiClient googleApiClient, List<AutocompletePrediction> resultPlaceList, Handler autoCompleteSelected) {
            this.context = context;
            this.resultPlaceList = resultPlaceList;
            this.googleApiClient = googleApiClient;
            this.autoCompleteSelected = autoCompleteSelected;
            mGeoDataClient = Places.getGeoDataClient(context, null);
        }
    
        @Override
        public PlaceAutoCompleteHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(context).inflate(R.layout.list_item_google_place_autocomplete, parent, false);
            return new PlaceAutoCompleteHolder(itemView);
        }
    
        @Override
        public void onBindViewHolder(final PlaceAutoCompleteHolder holder, final int position) {
            final AutocompletePrediction autocompletePrediction = resultPlaceList.get(position);
            holder.getLocationAddressView().setText(autocompletePrediction.getPrimaryText(null));
            holder.getLocationLocalityView().setText(autocompletePrediction.getSecondaryText(null));
            holder.getItemView().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mGeoDataClient.getPlaceById(autocompletePrediction.getPlaceId()).addOnCompleteListener(new OnCompleteListener<PlaceBufferResponse>() {
                        @Override
                        public void onComplete(@NonNull Task<PlaceBufferResponse> task) {
                            if (task.isSuccessful()) {
                                PlaceBufferResponse places = task.getResult();
                                Place myPlace = places.get(0);
                                googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myPlace.getLatLng(), 17));
                                autoCompleteSelected.sendMessage(Message.obtain());
                                Log.i("getPlaceById", "Place found: " + myPlace.getName());
                                places.release();
                            } else Log.e("getPlaceById", "Place not found.");
                        }
                    });
                    Toast.makeText(context, resultPlaceList.get(holder.getAdapterPosition()).getFullText(null), Toast.LENGTH_LONG).show();
                }
            });
        }
    
        @Override
        public int getItemCount() {
            return resultPlaceList.size();
        }
    
        @Override
        public Filter getFilter() {
            if (placeAutoCompleteFilter == null)
                placeAutoCompleteFilter = new PlaceAutoCompleteFilter(googleApiClient, this, resultPlaceList);
            return placeAutoCompleteFilter;
        }
    
        public void setGoogleMap(GoogleMap googleMap) {
            this.googleMap = googleMap;
        }
    }
    

    PlaceAutoCompleteFilter.java

    package com.equinox.prologix.Filters;
    
    import android.text.style.CharacterStyle;
    import android.util.Log;
    import android.widget.Filter;
    
    import com.equinox.prologix.Adapters.PlaceAutoCompleteAdapter;
    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.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.Place;
    import com.google.android.gms.location.places.Places;
    import com.google.android.gms.location.places.ui.PlaceAutocomplete;
    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;
    
    import static com.equinox.prologixappcommon.Models.DataHolderCommon.currentCountry;
    import static com.equinox.prologixappcommon.Models.DataHolderCommon.currentLocation;
    import static com.equinox.prologixappcommon.Utils.BackendTransform.transform;
    import static com.equinox.prologixappcommon.Utils.BackendTransform.transform2;
    import static com.google.android.gms.location.places.AutocompleteFilter.TYPE_FILTER_NONE;
    
    /**
     * Created by Mohammed Mukhtar on 12/1/2017.
     */
    
    public class PlaceAutoCompleteFilter extends Filter {
    
        private GoogleApiClient mGoogleApiClient;
        private PlaceAutoCompleteAdapter placeAutoCompleteAdapter;
        private List<AutocompletePrediction> resultPlaceList;
    
        public PlaceAutoCompleteFilter(GoogleApiClient mGoogleApiClient,
                                       PlaceAutoCompleteAdapter placeAutoCompleteAdapter,
                                       List<AutocompletePrediction> resultPlaceList) {
            this.mGoogleApiClient = mGoogleApiClient;
            this.placeAutoCompleteAdapter = placeAutoCompleteAdapter;
            this.resultPlaceList = resultPlaceList;
        }
    
        @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.
                List<AutocompletePrediction> tempResult = getAutoComplete(constraint);
                if (tempResult != null) {
                    results.values = tempResult;
                    results.count = tempResult.size();
                }
            }
            return results;
        }
    
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results != null && results.count > 0) {
                resultPlaceList.clear();
                resultPlaceList.addAll((List<AutocompletePrediction>) results.values);
                placeAutoCompleteAdapter.notifyDataSetChanged();
            }
            else {
                // The API did not return any results, invalidate the data set.
    
            }
        }
    
        private ArrayList<AutocompletePrediction> getAutoComplete(CharSequence constraint) {
            if (mGoogleApiClient.isConnected()) {
                Log.i("", "Starting autocomplete query for: " + constraint);
    
                AutocompleteFilter autocompleteFilter = new AutocompleteFilter.Builder()
                        //.setCountry(currentCountry.getCountryCode())
                        .setTypeFilter(TYPE_FILTER_NONE)
                        .build();
    
                // 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(),
                                        new LatLngBounds.Builder().include(transform(currentLocation)).build(),
                                        autocompleteFilter);
    
                // 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<AutocompletePrediction> resultList = new ArrayList<>(autocompletePredictions.getCount());
                while (iterator.hasNext()) {
                    AutocompletePrediction prediction = iterator.next();
                    resultList.add(prediction.freeze());
                }
    
                // 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;
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题