简体   繁体   中英

Searching listview with custom ArrayAdapter

I have a listview that has a custom adapter, and I was trying to make it searchable using an Action Item. When I click the search icon in the action bar, the edit text comes up, but when I enter text and click "done" on the keyboard, nothing happens.

Here is the main class:

public class ItemId extends SherlockListActivity {

    EditText editsearch;
    ArrayAdapter<String> adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Context ctx = getApplication();
        Resources res = ctx.getResources();

        String[] options = res.getStringArray(R.array.item_ids);
        String[] ids = res.getStringArray(R.array.item_names);
        TypedArray icons = res.obtainTypedArray(R.array.item_images);

        adapter = new ItemIDAdapter(ctx, R.layout.idslistitem, ids, options, icons);

        setListAdapter(adapter );
    }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Get the options menu view from menu.xml in menu folder
            getSupportMenuInflater().inflate(R.menu.items_menu, menu);

            // Locate the EditText in menu.xml
            editsearch = (EditText) menu.findItem(R.id.menu_search).getActionView();

            // Capture Text in EditText
            editsearch.addTextChangedListener(textWatcher);

            // Show the search menu item in menu.xml
            MenuItem menuSearch = menu.findItem(R.id.menu_search);

            menuSearch.setOnActionExpandListener(new OnActionExpandListener() {

                // Menu Action Collapse
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Empty EditText to remove text filtering
                    editsearch.setText("");
                    editsearch.clearFocus();
                    return true;
                }

                // Menu Action Expand
                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Focus on EditText
                    editsearch.requestFocus();

                    // Force the keyboard to show on EditText focus
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
                    return true;
                }
            });

            // Show the settings menu item in menu.xml
            MenuItem menuSettings = menu.findItem(R.id.home);

            // Capture menu item clicks
            menuSettings.setOnMenuItemClickListener(new OnMenuItemClickListener() {

                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    Intent intent2 = new Intent(ItemId.this, Home.class);
                    startActivity(intent2);
                    return true;
                }

            });

            return true;
        }

        // EditText TextWatcher
        private TextWatcher textWatcher = new TextWatcher() {

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub
                String text = editsearch.getText().toString()
                        .toLowerCase(Locale.getDefault());
                adapter.getFilter().filter(text);
            };


            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub

            }

        };
}

And here is the Adapter class:

public class ItemIDAdapter extends ArrayAdapter<String> implements Filterable {

    public LayoutInflater mInflater;

    public String[] mStrings;
    public String[] mIds;
    public TypedArray mIcons;   
    public int mViewResourceId;

    public ItemIDAdapter(Context ctx, int viewResourceId,
            String[] strings, String[] ids, TypedArray icons) {
        super(ctx, viewResourceId, strings);

        mInflater = (LayoutInflater)ctx.getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);

        mStrings = strings;
        mIds = ids;
        mIcons = icons;       
        mViewResourceId = viewResourceId;
    }

    @Override
    public int getCount() {
        return mStrings.length;
    }

    @Override
    public String getItem(int position) {
        return mStrings[position];
    }

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



    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        convertView = mInflater.inflate(mViewResourceId, null);

        ImageView iv = (ImageView)convertView.findViewById(R.id.option_icon);
        iv.setImageDrawable(mIcons.getDrawable(position));

        TextView tv = (TextView)convertView.findViewById(R.id.option_text);
        tv.setText(mStrings[position]);

        TextView tv1 = (TextView)convertView.findViewById(R.id.itemids);
        tv1.setText(mIds[position]);

        return convertView;
    }


}

If anyone has any idea as to why nothing happens when I search, or knows how to fix it, it'd be greatly appreciated. Thanks!!

You need to implement a custom filter. Have a look at this post here someone else has had a similar problem which he solved: https://stackoverflow.com/a/8258457/2045570

Below is mine code, which is working perfectly:-

public class ExpenditureAdapter extends ArrayAdapter<Expenditure> implements Filterable {
ArrayList<Expenditure> listArray;
ArrayList<Expenditure> filteredlistArray;
private Filter mFilter;
public ExpenditureAdapter(@NonNull Context context, ArrayList<Expenditure> list) {
    super(context,0, list);
    listArray=list;
    filteredlistArray=list;
}
@Override
public int getCount() {
    return filteredlistArray.size();    // total number of elements in the list
}

public void add(Expenditure object) {
    listArray.add(object);
    this.notifyDataSetChanged();
}

public Filter getFilter() {
    if (mFilter == null) {
        mFilter = new CustomFilter();
    }
    return mFilter;
}
@Override
public Expenditure getItem(int i) {
    return filteredlistArray.get(i);    // single item in the list
}
@Override
public void notifyDataSetChanged() {
    super.notifyDataSetChanged();
}
@Override
public long getItemId(int i) {
    return i;                   // index number
}
@Override

public View getView(int position, View convertView, ViewGroup parent) {

    // Get the data item for this position

    Expenditure expenditure = getItem(position);

    // Check if an existing view is being reused, otherwise inflate the view

    if (convertView == null) {

        convertView = LayoutInflater.from(getContext()).inflate(R.layout.listexpenditure, parent, false);

    }

    // Lookup view for data population

    TextView ExpId = (TextView) convertView.findViewById(R.id.ExpId);
    TextView ExDate = (TextView) convertView.findViewById(R.id.ExDate);
    TextView ExpAmt = (TextView) convertView.findViewById(R.id.ExpAmt);
    TextView ExpDetail = (TextView) convertView.findViewById(R.id.ExpDetail);
 

    // Populate the data into the template view using the data object

    ExpId.setText(expenditure.ExpId);
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
    String dateTime = dateFormat.format(expenditure.ExpDate);
    ExDate.setText(dateTime);
    ExpAmt.setText(String.valueOf(expenditure.ExpAmt));
    ExpDetail.setText(expenditure.ExpDetail);
    return convertView;

}


private class CustomFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();

        if(constraint == null || constraint.length() == 0) {
            ArrayList<Expenditure> list = new ArrayList<Expenditure>(listArray);
            results.values = list;
            results.count = list.size();
        } else {
            ArrayList<Expenditure> newValues = new ArrayList<Expenditure>();
            for(int i = 0; i < listArray.size(); i++) {
                Expenditure e_item = listArray.get(i);
                if(e_item.ExpDetail.contains(constraint)) {
                    newValues.add(e_item);
                }
            }
            results.values = newValues;
            results.count = newValues.size();
        }
        return results;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint,
                                  FilterResults results) {
        filteredlistArray = (ArrayList<Expenditure>) results.values;
      
        notifyDataSetChanged();
    }
}

and use it in your code as below:-

private TextWatcher textWatcher = new TextWatcher() {
    @Override
    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub
        String text = txtSearch.getText().toString()
                .toLowerCase(Locale.getDefault());
        adapter.getFilter().filter(text);
    };


    @Override
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                                  int arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                              int arg3) {
        // TODO Auto-generated method stub

    }

};

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