AutoCompleteTextView with Custom Adapter filtering

2019-01-20 06:49发布

问题:

I have a autocomplete text view in my android project which is working fine but it only works if first value is entered in it. So for making it more customizable, I have added the below class

public class CustomArrayAdapterWIthFilter extends ArrayAdapter<String> implements Filterable {
List<String> items = null;
List<String> originalItems = null;
private MyFilters myFilters = null;
Context mContext;

public CustomArrayAdapterWIthFilter(@NonNull Context context, @LayoutRes int resource, @NonNull List<String> objects) {
    super(context, resource, objects);
    this.items = new ArrayList<>();
    items.addAll(objects);
    this.originalItems = new ArrayList<>();
    this.originalItems.addAll(objects);
    mContext = context;
}

@Override
public int getCount() {
    return items.size();
}

@Nullable
@Override
public String getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public void notifyDataSetChanged() {
    super.notifyDataSetChanged();
}

@NonNull
@Override
public Filter getFilter() {
    if (myFilters == null) {
        myFilters = new MyFilters();
    }
    return myFilters;
}

class MyFilters extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults result = new FilterResults();

        if (constraint != null && constraint.toString().length() > 0) {
            ArrayList<String> filteredItems = new ArrayList<String>();

            for (int i = 0, l = originalItems.size(); i < l; i++) {
                String item = originalItems.get(i);
                if (item.toString().toLowerCase().contains(constraint))
                    filteredItems.add(item);
            }
            result.count = filteredItems.size();
            result.values = filteredItems;
        } else {
            synchronized (this) {
                result.values = originalItems;
                result.count = originalItems.size();
            }
        }
        return result;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        items = (ArrayList<String>) results.values;
        notifyDataSetChanged();
        clear();
        for (int i = 0, l = items.size(); i < l; i++)
            add(items.get(i));
        notifyDataSetInvalidated();
    }
}

public void addItems(List<String> items) {
    this.items = items;
    notifyDataSetChanged();
}

In my fragment I have done the following

CustomArrayAdapterWIthFilter meterSrNumAdapter;
 if (meterSrNumAdapter.getCount() == 0) {
            meterSrArrayList = new MeterManager(getActivity()).getRefNoByStatus(Constants.SR_NO_UN_USED);
            meterSrArrayList.add(installationDetails.getMsn());
            meterSrNumAdapter.addItems(meterSrArrayList);
        }
 if (meterSrNumAdapter.getCount() == 0) {
            meterSrArrayList = new MeterManager(getActivity()).getRefNoByStatus(Constants.SR_NO_UN_USED);
            meterSrNumAdapter.addItems(meterSrArrayList);
        }

meterSrArrayList = new ArrayList<String>();
    meterSrNumAdapter = new CustomArrayAdapterWIthFilter(getActivity(), R.layout.custom_spinner_layout, meterSrArrayList);
    smartMsnSpinner.setAdapter(meterSrNumAdapter);
    smartMsnSpinner.setSingleLine(true);
    smartMsnSpinner.setThreshold(1);

    smartMsnSpinner.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
           selectedMeterNo = adapterView.getItemAtPosition(i).toString();
            Log.d("testtt", adapterView.getItemAtPosition(i).toString());
        }


    });

In above code smartMsnSpinner is my autocomplete text view

When I run my app the autocomplete doesn't works. I have tried some other adapters which are placed over the internet. But still the result is same. I am trying for this custom adapter because in my another app it's working perfect and in this code I am doing the same.

Update 1

After the suggestion I have changed the custom adapter code while considering the other part of the code is same as added above

List<String> suggestionItems = null;

//In constructor
this.items = new ArrayList<>(objects);

this.originalItems = new ArrayList<>(objects);

mContext = context;

class MyFilters extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        if(constraint !=null)
        {
            suggestionItems.clear();

            for(int i=0, i1 = originalItems.size(); i <i1; i++)
            {
                String item = originalItems.get(i);
                if(item.toString().toLowerCase().contains(constraint))
                    suggestionItems.add(item);
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = suggestionItems;
            filterResults.count = suggestionItems.size();
            return filterResults;
        }
        else
        {
            return new FilterResults();
        }

    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
         if(results !=null && results.count > 0)
         {
             items.clear();
             items = (ArrayList<String>)results.values;
             notifyDataSetChanged();
         }
         else
         {
             items.addAll(originalItems);
         }
    }
}

Any help would be highly appreciated.

回答1:

In Constructor no need to use add all , you can assign like this and create one more in adapter ,

List<String> suggestionItems = null;

//constructor should be like this 

this.items = new ArrayList<>(objects);
this.originalItems = new ArrayList<>(objects);
this.suggestionItems = new ArrayList<>();

and filter should be

class MyFilters extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        if (constraint != null)
        {
            suggestionItems .clear();
            for (int i = 0, l = originalItems.size(); i < l; i++) {
                String item = originalItems.get(i);
                if (item.toString().toLowerCase().contains(constraint))
                    suggestionItems .add(item);
            }
            FilterResults filterResults = new FilterResults();
            filterResults.values = suggestionItems ;
            filterResults.count = suggestionItems .size();
            return filterResults;
        }
        else
        {
            return new FilterResults();
        }
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        if (results != null && results.count > 0) {
            items.clear();
            items = (ArrayList<String>) results.values;
            notifyDataSetChanged();
        }
        else {
            items .addAll(originalItems );
        }
    }
}