简体   繁体   中英

How to implement Search in a Custom ListView in android?

I have an edittext and a listview in my application my listview show contact list. I want listview filter with edittext. I searched a lot on google and found some examles but none worked for me here's my code my custom adapter

public class MainActivity extends AppCompatActivity {

private static final int CODE_GET_REQUEST = 1024;
private static final int CODE_POST_REQUEST = 1025;

EditText editTextHeroId, editTextName, editTextRealname, editTextComment;
Spinner spinnerTeam;
ProgressBar progressBar;
ListView listView;
Button buttonAddUpdate;
Button buttonScan;
SearchView searchView;
Adapter HeroAdapter;

private List<Hero> heroList = new ArrayList<Hero>();
boolean isUpdating = false;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    editTextHeroId = (EditText) findViewById(R.id.editTextHeroId);
    editTextName = (EditText) findViewById(R.id.editTextName);
    editTextRealname = (EditText) findViewById(R.id.editTextRealname);
    editTextComment = (EditText) findViewById(R.id.editTextComment);
    spinnerTeam = (Spinner) findViewById(R.id.spinnerTeamAffiliation);

    buttonAddUpdate = (Button) findViewById(R.id.buttonAddUpdate);
    buttonScan = (Button) findViewById(R.id.buttonScan);

    progressBar = (ProgressBar) findViewById(R.id.progressBar);
    listView = (ListView) findViewById(R.id.listViewHeroes);
    listView.setTextFilterEnabled(true);
    heroList = new ArrayList<>();

    HeroAdapter adapter = new HeroAdapter(heroList);
    final ArrayAdapter<Hero> HeroAdapter = new ArrayAdapter<Hero>(this, R.layout.layout_hero_list, heroList);
    listView.setAdapter(adapter);

    editTextName.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
            HeroAdapter.getFilter().filter(cs);
        }

        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { }

        @Override
        public void afterTextChanged(Editable arg0) {}

    });

Adapter

public class HeroAdapter extends ArrayAdapter<Hero> implements Filterable {

    List<Hero> heroList;

    public HeroAdapter(List<Hero> heroList) {
        super(MainActivity.this, R.layout.layout_hero_list, heroList);
        this.heroList = heroList;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = getLayoutInflater();
        View listViewItem = inflater.inflate(R.layout.layout_hero_list, null, true);

        final TextView textViewName = listViewItem.findViewById(R.id.textViewName);
        TextView textViewUpdate = listViewItem.findViewById(R.id.textViewUpdate);
        TextView textViewDelete = listViewItem.findViewById(R.id.textViewDelete);

        final Hero hero = heroList.get(position);

        textViewName.setText(hero.getName());

        textViewUpdate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isUpdating = true;
                editTextHeroId.setText(String.valueOf(hero.getId()));
                editTextName.setText(hero.getName());
                editTextRealname.setText(hero.getRealname());
                editTextComment.setText(hero.getRating());
                spinnerTeam.setSelection(((ArrayAdapter<String>) spinnerTeam.getAdapter()).getPosition(hero.getTeamaffiliation()));
                buttonAddUpdate.setText("Update");
            }
        });

        textViewDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

                builder.setTitle("Delete " + hero.getName())
                        .setMessage("Are you sure you want to delete it?")
                        .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                deleteHero(hero.getId());
                            }
                        })
                        .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                            }
                        })
                        .setIcon(android.R.drawable.ic_dialog_alert)
                        .show();
            }
        });
        return listViewItem;
    }

    public Filter getFilter() {

        Filter filter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {

                heroList = (List<Hero>) results.values;
                notifyDataSetChanged();
            }

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {

                FilterResults results = new FilterResults();
                ArrayList<Hero> heroList = new ArrayList<Hero>();

                // perform your search here using the searchConstraint String.

                constraint = constraint.toString().toLowerCase();
                for (int i = 0; i < heroList.size(); i++) {
                    Hero dataNames = heroList.get(i);
                    if (dataNames.toString().toLowerCase().startsWith(constraint.toString()))  {
                        heroList.add(dataNames);
                    }
                }

                results.count = heroList.size();
                results.values = heroList;
                Log.e("VALUES", results.values.toString());

                return results;
            }
        };

        return filter;
    }
}

when i fill the keyword from edittext, the list data can't show, . any help will be appriciated. thanks in advance

the heroList.size() is always 0 so will not go inside the "for (int i = 0; i < heroList.size(); i++)" at all

You have to remove "ArrayList heroList = new ArrayList();" to select the GLOBAL heroList.

protected FilterResults performFiltering(CharSequence constraint) {

            FilterResults results = new FilterResults();
            **ArrayList<Hero> heroList = new ArrayList<Hero>();**

            // perform your search here using the searchConstraint String.

            constraint = constraint.toString().toLowerCase();
            for (int i = 0; i < heroList.size(); i++) {
                Hero dataNames = heroList.get(i);
                if (dataNames.toString().toLowerCase().startsWith(constraint.toString()))  {
                    heroList.add(dataNames);
                }
            }

            results.count = heroList.size();
            results.values = heroList;
            Log.e("VALUES", results.values.toString());

            return results;
        }

First, at the top of the activity

Adapter HeroAdapter;

Should be

HeroAdapter adapter;

Then you need to actually initialize that one, not a different adapter, or even two of them

this.heroList = new ArrayList<>();
this.adapter = new HeroAdapter(this, heroList);
listView.setAdapter(adapter);

After you fix the constructor for the adapter to accept a Context instead of being coupled to the MainActivity

public class HeroAdapter extends ArrayAdapter<Hero> implements Filterable {

    private List<Hero> heroList;

    public HeroAdapter(Context c, List<Hero> heroList) {
        super(c, R.layout.layout_hero_list, heroList);
        this.heroList = heroList;
    }

Then you're also "shadowing" your list with an empty one when you try to filter. Android Studio might even be pointing this out to you, if you read the warnings.

Rename it to something else

FilterResults results = new FilterResults();
List<Hero> filtered = new ArrayList<>();
constraint = constraint.toString().toLowerCase();
for (Hero h : MainActivity.this.heroList) {
     if (h.getName().toLowerCase().startsWith(constraint))  {
         filtered.add(h);
     }
 }

results.count = filtered.size();
results.values = filtered;
return results;

You have used class name of adapter in onTextChanged() method instead of object of adapter.

Try this:

 @Override
    public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
        String text = editTextName.getText().toString().toLowerCase(Locale.getDefault());
        adapter.filter(text);
    }

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