简体   繁体   中英

Filter on list doesn't work properly

I'm having troubles with the following code. I'm trying to filter a ListView. The content is downloaded from Firebase, but that shouldn't be the source of the problem. I'd like the content of the list to be updated while the user writes. It actually works but the problem is when the user deletes a character : the list only updates with the result from the precedent research. So for example with the initial list : "Madrid", "Mainly". If the users writes "Mad", "Madrid" will be the only one to be displayed. But when he will delete the "d" ("Ma" left), "Mainly" won't be displayed.

A weird thing is that when I don't use clear() and addAll(values) in publishResult from my adapter, deleting characters works, but the filtering is done only in number of elements. For example for a list of 100 elements, if 14 match, only the first 14 elements are displayed and not the 14 matching elements.

If anyone sees why I'm wrong with this code, an answer would be welcome :)

Adapter

import android.content.Context;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.util.Log;
import java.util.ArrayList;

public class AdapterCourseList extends ArrayAdapter<String> {
    public Context context;
    public ArrayList<String> values;
    final public ArrayList<String> originalValues;
    private static final String TAG = AdapterCourseList.class.getSimpleName();

    public AdapterCourseList(Context context, ArrayList<String> valeurs){
        super(context, android.R.layout.simple_list_item_1, valeurs);
        this.context = context;
        this.values = valeurs;
        this.originalValues = valeurs;
    }

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

    public Filter getFilter() {
        Filter mfilter = new Filter() {
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                values = (ArrayList<String>)results.values;
                clear();
                notifyDataSetChanged();
                addAll(values);
            }

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

                ArrayList<String> res = new ArrayList<>();
                for(String d: originalValues){
                    Log.d(TAG,d);

                    if(d.toUpperCase().contains(constraint.toString().toUpperCase())){
                        res.add(d);

                    }
                }

                result.count = res.size();
                result.values = res;

                return result;
            }
        };

        return mfilter;
    }
}

Activity

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;

import java.util.ArrayList;

public class CourseListActivity extends AppCompatActivity {
    private EditText edit_search;
    private AdapterCourseList adapter;
    private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course_list);

        SimpleFirebase ref = new SimpleFirebase(this);
        final ArrayList<String> stringList = ref.getCurses();

        edit_search = (EditText) findViewById(R.id.edit_search);
        listView = (ListView) findViewById(R.id.courseList);
        adapter = new AdapterCourseList(this, stringList);
        listView.setAdapter(adapter);

        edit_search.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) {
                adapter.getFilter().filter(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String d = adapter.getItem(position);

                Intent i = new Intent(CourseListActivity.this, AddFormActivity.class);
                i.putExtra("Course", d);

                CourseListActivity.this.setResult(1, i);
                CourseListActivity.this.finish();
            }
        });
    }
}

You are overriding all these methods in ArrayAdapter -- and you probably don't have to.

ArrayAdapter already implements Filterable and will return a Filter that does a case-insensitive comparison like you are doing. You should try just using the default implementation since there's a good chance it will do what you want.

The problem occurs because clear() and addAll() operate on ArrayAdapter 's internal list. However, you are using your own list for getCount() , so your adapter has a bit of a split personality. If you need to override methods, try extending BaseAdapter ; you'll have a few more lines of code, but it will be a lot more clear where all the state is coming from.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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