简体   繁体   English

Android-Google 将 api 自动完成与回收站视图一起放置?

[英]Android- Google places api autocomplete with recycler view?

I am new to Android and trying to develop an app which has a map feature along with places auto complete.I am using google places Api to make my own custom autocomplete with a Recycler view.我是 Android 新手,正在尝试开发一个具有地图功能和地点自动完成功能的应用程序。我正在使用谷歌地点 Api 使用 Recycler 视图制作我自己的自定义自动完成功能。 Everything's working fine except the Recycler view displays prediction even after clearing the search edit text.一切正常,除了 Recycler 视图即使在清除搜索编辑文本后也会显示预测。 It occurs only when I delete the text fastly.If the text is changed slowly the recyler view is cleared otherwise not.I have tried around but couldn't find a solution.Posting my adapter and activity code.它仅在我快速删除文本时发生。如果文本更改缓慢,则回收器视图会被清除,否则不会。我已经尝试过但找不到解决方案。发布我的适配器和活动代码。 Any help will be appreciated任何帮助将不胜感激

 public class AutoCompleteAdapter extends RecyclerView.Adapter<AutoCompleteAdapter.PredictionHolder> implements Filterable{
    private static final String TAG = AutoCompleteAdapter.class.getSimpleName();

    public interface PlaceAutoCompleteInterface{
         void onPlaceClick(ArrayList<PlaceAutoComplete> mResultList,int position);
    }

    private ArrayList<PlaceAutoComplete> mResultList;
    private Context mContext;
    private int mLayout;
    private GoogleApiClient mGoogleApiClient;
    private AutocompleteFilter mPlaceFilter;
    private LatLngBounds mBounds;

    private PlaceAutoCompleteInterface mPlaceClickInterface;

    public AutoCompleteAdapter(Context mContext,int mLayout,GoogleApiClient mGoogleApiClient,LatLngBounds mBounds,AutocompleteFilter mPlaceFilter,PlaceAutoCompleteInterface mPlaceClickInterface){
        this.mContext=mContext;
        this.mLayout=mLayout;
        this.mGoogleApiClient=mGoogleApiClient;
        this.mPlaceFilter=mPlaceFilter;
        this.mBounds=mBounds;
        this.mPlaceClickInterface=mPlaceClickInterface;
    }

    /**
     * Setting Bounds for subsequent queries
     */
    public void setmBounds(LatLngBounds mBounds){
        this.mBounds=mBounds;
    }

    /*
   Clear List items
    */
    public void clearList(){
        if(mResultList!=null && mResultList.size()>0){
            mResultList.clear();
        }
    }

    public static class PredictionHolder extends RecyclerView.ViewHolder{
        private TextView mAddress1,mAddress2;
        private LinearLayout mPredictionLayout;
        public PredictionHolder(View holder){
            super(holder);
            mAddress1=(TextView)holder.findViewById(R.id.primary_address);
            mAddress2=(TextView)holder.findViewById(R.id.secondary_address);
            mPredictionLayout=(LinearLayout)holder.findViewById(R.id.prediction_layout);
        }
    }

    /**
     * Holder class for query result
     */
    public class PlaceAutoComplete{
        private CharSequence placeId;
        private CharSequence placeAddress1,placeAddress2;

        public PlaceAutoComplete(CharSequence placeId,CharSequence placeAddress1,CharSequence placeAddress2){
            this.placeId=placeId;
            this.placeAddress1=placeAddress1;
            this.placeAddress2=placeAddress2;
        }

        public String getPlaceAddress1(){
            return placeAddress1.toString();
        }
        public String getPlaceAddress2(){
            return placeAddress2.toString();
        }

        public String getPlaceId(){
            return placeId.toString();
        }

    }


    @Override
    public Filter getFilter() {
       Filter filter=new Filter() {
           @Override
           protected FilterResults performFiltering(CharSequence constraint) {

               FilterResults results=new FilterResults();
               ArrayList<PlaceAutoComplete> queryResults;
               if(constraint!=null && constraint.length()>0) {
                   queryResults = getAutoComplete(constraint);
                   if(queryResults!=null){
                       results.values = queryResults;
                       results.count = queryResults.size();
                   }
               }
               // The API successfully returned results.
               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<PlaceAutoComplete>) results.values;
                    notifyDataSetChanged();
                }else{
                    // The API did not return any results, invalidate the data set.
                    clearList();
                    notifyDataSetChanged();
                }
           }
       };
        return filter;
    }

    /**
     * Method to call API for each user input
     * @param constraint User input character string
     * @return ArrayList containing suggestion results
     */
    private ArrayList<PlaceAutoComplete> getAutoComplete(CharSequence constraint){
        if(mGoogleApiClient.isConnected()){
            //Making a query and fetching result in a pendingResult

            PendingResult<AutocompletePredictionBuffer> results= Places.GeoDataApi
                    .getAutocompletePredictions(mGoogleApiClient,constraint.toString(),mBounds,mPlaceFilter);

            //Block and wait for 60s for a result
            AutocompletePredictionBuffer autocompletePredictions=results.await(60, TimeUnit.SECONDS);

            final Status status=autocompletePredictions.getStatus();

            // Confirm that the query completed successfully, otherwise return null
            if(!status.isSuccess()){
                Log.e(TAG, "Error getting autocomplete prediction API call: " + status.toString());
                autocompletePredictions.release();
                return null;
            }

            Log.i(TAG, "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();
                resultList.add(new PlaceAutoComplete(prediction.getPlaceId(),prediction.getPrimaryText(null),prediction.getSecondaryText(null)));
            }
            autocompletePredictions.release();
            return resultList;
        }else{
            Log.e(TAG,"GoogleApiClient Not Connected");
            return  null;
        }
    }


    @Override
    public PredictionHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater mLayoutInflater=(LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View convertView=mLayoutInflater.inflate(mLayout,parent,false);
        PredictionHolder predictionHolder=new PredictionHolder(convertView);
        return predictionHolder;
    }

    @Override
    public void onBindViewHolder(PredictionHolder holder, final int position) {
        holder.mAddress1.setText(mResultList.get(position).getPlaceAddress1());
        holder.mAddress2.setText(mResultList.get(position).getPlaceAddress2());
        holder.mPredictionLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mPlaceClickInterface.onPlaceClick(mResultList,position);
            }
        });
    }

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

    public PlaceAutoComplete getItem(int position) {
            return mResultList.get(position);
    }

}

Activity code活动代码

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener, AutoCompleteAdapter.PlaceAutoCompleteInterface {

    private static final String TAG = MapsActivity.class.getSimpleName();
    private static final int MY_PERMISSIONS_ACCESS_FINE_LOCATION = 1;
    private static final int REQUEST_CHECK_SETTINGS = 2;

    private static final LatLngBounds BOUNDS_INDIA = new LatLngBounds(
            new LatLng(23.63936, 68.14712), new LatLng(28.20453, 97.34466));


    private GoogleMap mMap;
    private Button mSelectButton;
    private TextView mPrimaryAddress, mSecondaryAddress;
    private LinearLayout mAddressLayout;
    private ImageButton mCurrentLocation;
    private Location mLocation;
    private LocationRequest mLocationRequest;

    protected GoogleApiClient mGoogleApiClient;

    private Double mLatitude, mLongitude;

    private EditText mSearchText;
    private RecyclerView mRecyclerView;
    private AutoCompleteAdapter mAdapter;
    private ImageView mCustomMarker;

    private static boolean sCameraMoved = true;

    private AddressResultReceiver mAddressResultReceiver;


    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    @Override
    protected void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        if (isGooglePlayServicesAvailable()) {
            buildGoogleAPiClient();
        } else {
            Log.e(TAG, "Google Play Services not available");
        }
        createLocationRequest();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        mSelectButton = (Button) findViewById(R.id.select_button);
        mPrimaryAddress = (TextView) findViewById(R.id.firstAddress);
        mSecondaryAddress = (TextView) findViewById(R.id.secondAddress);
        mAddressLayout = (LinearLayout) findViewById(R.id.address_layout);

        mCurrentLocation = (ImageButton) findViewById(R.id.get_current_location);
        mCustomMarker = (ImageView) findViewById(R.id.map_custom_marker);

        mSearchText = (EditText) findViewById(R.id.search_box);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        MapFragment mapFragment = ((MapFragment)getFragmentManager().findFragmentById(R.id.map));
        mapFragment.getMapAsync(this);

        isGpsOn();

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
        mAdapter = new AutoCompleteAdapter(this, R.layout.layout_recommendation, mGoogleApiClient, BOUNDS_INDIA, null, this);
        mRecyclerView.setAdapter(mAdapter);


        mAddressResultReceiver = new AddressResultReceiver(null);

        mSearchText.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                mSearchText.setCursorVisible(true);
                return false;
            }
        });

        mSearchText.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 (!s.equals("") && mGoogleApiClient.isConnected()) {
                    mAdapter.getFilter().filter(s.toString());
                } else if (!mGoogleApiClient.isConnected()) {
                    Log.e(TAG, "API  NOT CONNECTED");
                }
            }

            @Override
            public void afterTextChanged(Editable s) {
                if(s.toString().equals("")){
                    mAdapter.getFilter().filter(null);
                }
            }
        });

        mCurrentLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isGpsOn();
            }
        });

        mSelectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mLongitude != null && mLongitude != null) {
                    Intent resultIntent = new Intent();
                    resultIntent.putExtra("address1", mPrimaryAddress.getText().toString());
                    resultIntent.putExtra("address2", mSecondaryAddress.getText().toString());
                    resultIntent.putExtra("latitude", mLatitude);
                    resultIntent.putExtra("longitude", mLongitude);
                    setResult(Activity.RESULT_OK, resultIntent);
                    MapsActivity.this.finish();
                } else {
                    Toast.makeText(getBaseContext(), "Select a location", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    /**
     * Method to initialize LocationRequest
     */
    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY | LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    }

    // Function to build the Google Api Client..
    protected synchronized void buildGoogleAPiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addOnConnectionFailedListener(this)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API)
                .addApi(Places.GEO_DATA_API)
                .build();
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(20.5937, 78.9629), 4.0f));
    }


    @Override
    public void onPlaceClick(ArrayList<AutoCompleteAdapter.PlaceAutoComplete> mResultList, int position) {
        if (mResultList != null) {
            try {
                String placeId = String.valueOf(mResultList.get(position).getPlaceId());

                mSearchText.setText("");
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(mSearchText.getWindowToken(), 0);
                mSearchText.setCursorVisible(false);
                PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.getPlaceById(mGoogleApiClient, placeId);
                placeResult.setResultCallback(new ResultCallback<PlaceBuffer>() {
                    @Override
                    public void onResult(@NonNull PlaceBuffer places) {
                        if (!places.getStatus().isSuccess()) {
                            // Request did not complete successfully
                            Log.e(TAG, "Place query did not complete. Error: " + places.getStatus().toString());
                            places.release();
                            return;
                        }
                        Place place = places.get(0);
                        mLatitude = place.getLatLng().latitude;
                        mLongitude = place.getLatLng().longitude;
                        mPrimaryAddress.setText(place.getName());
                        mSecondaryAddress.setText(place.getAddress());
                        mAddressLayout.setVisibility(View.VISIBLE);
                        sCameraMoved = false;
                        loadMap();
                        places.release();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG, e.toString());
            }
        }
    }


    /**
     * Method to display the location on Map
     */
    public void loadMap() {
        if (mLatitude != null && mLongitude != null) {
            CameraPosition cameraPosition = new CameraPosition.Builder()
                    .target(new LatLng(mLatitude, mLongitude))      // Sets the center of the map to location user
                    .zoom(18)                   // Sets the zoom// Sets the tilt of the camera to 30 degrees
                    .build();                   // Creates a CameraPosition from the builder
            mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
            mCustomMarker.setVisibility(View.VISIBLE);

            mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
                @Override
                public void onCameraIdle() {
                    Location location = new Location("");
                    if (sCameraMoved) {
                        mLatitude = mMap.getCameraPosition().target.latitude;
                        mLongitude = mMap.getCameraPosition().target.longitude;
                        location.setLatitude(mLatitude);
                        location.setLongitude(mLongitude);
                        convertLocationToAddress(location);
                    }
                    sCameraMoved = true;
                }
            });
        }
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        startLocationUpdates();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_ACCESS_FINE_LOCATION: {
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    mCurrentLocation.setVisibility(View.VISIBLE);
                } else {
                    mCurrentLocation.setVisibility(View.GONE);
                }
                return;
            }
        }
    }

    protected void startLocationUpdates() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_ACCESS_FINE_LOCATION);
                Log.d(TAG, "Permission Not Granted");
            }

        } else {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        }
    }

    /**
     * Method to stop the regular location updates
     */
    protected void stopLocationUpdates() {
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(
                    mGoogleApiClient, this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        stopLocationUpdates();
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.e(TAG, "Connection Suspended");
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e(TAG, "Connection Failed");
    }

    @Override
    public void onLocationChanged(Location location) {
        mLocation = location;
    }


    /**
     * Method to get current location and do reverse geocoding of the location
     */
    private void getCurrentLocationAddress() {
        if (mLocation != null) {
            mLatitude = mLocation.getLatitude();
            mLongitude = mLocation.getLongitude();
            convertLocationToAddress(mLocation);
            loadMap();
        }
    }

    /**
     * Method to check if google play services are enabled or not
     *
     * @return boolean status
     */
    public boolean isGooglePlayServicesAvailable() {
        GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
        int status = googleApiAvailability.isGooglePlayServicesAvailable(this);
        if (status != ConnectionResult.SUCCESS) {
            if (googleApiAvailability.isUserResolvableError(status)) {
                googleApiAvailability.getErrorDialog(this, status, 2404).show();
            }
            return false;
        }
        return true;
    }

    /**
     * Method to check if GPS is on or not
     */
    private void isGpsOn() {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(mLocationRequest);

        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        getCurrentLocationAddress();
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            status.startResolutionForResult(
                                    MapsActivity.this,
                                    REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            Log.e(TAG, "Exception : " + e);
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        Log.e(TAG, "Location settings are not satisfied.");
                        break;
                }
            }
        });

    }

    /**
     * Method to convert latitude and longitude to  address via reverse-geocoding
     */
    private void convertLocationToAddress(Location location) {
        Intent intent = new Intent(this, GeoCoderIntentService.class);
        intent.putExtra(Constants.RECEIVER, mAddressResultReceiver);
        intent.putExtra(Constants.LOCATION_DATA_EXTRA, location);
        startService(intent);
    }


    private class AddressResultReceiver extends ResultReceiver {

        public AddressResultReceiver(Handler handler) {
            super(handler);
        }

        protected void onReceiveResult(final int resultCode, Bundle resultData) {

            final String address1 = resultData.getString(Constants.ADDRESS_DATA_KEY1);
            final String address2 = resultData.getString(Constants.ADDRESS_DATA_KEY2);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (resultCode == Constants.SUCCESS_RESULT) {
                        mPrimaryAddress.setText(address1);
                        mSecondaryAddress.setText(address2);
                        mAddressLayout.setVisibility(View.VISIBLE);
                    } else {
                        Log.e(TAG, "Error while fetching data");
                        mLatitude = mLongitude = null;
                        mPrimaryAddress.setText(address1);
                        mSecondaryAddress.setText("");
                    }
                }
            });
        }
    }

}

Try to change your code like below,尝试更改您的代码,如下所示,

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

            if (!s.equals("")) {
              if(mGoogleApiClient.isConnected()){
                mAdapter.getFilter().filter(s.toString());
               }else{
                Log.e(TAG, "API  NOT CONNECTED");                  
                  }

            } else {
                mAdapter.mResultList.clear();//make mResultList as public
                mAdapter.notifyDataSetChanged();

            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM