【问题标题】:Search Filter is not working搜索过滤器不起作用
【发布时间】:2015-03-12 10:18:00
【问题描述】:

即使我在 EditText 中输入准确的“键”名称也没有发生任何事情,而它必须只在列表中显示该记录。

过滤不起作用,这就是我的 JSON 的样子:

{
  "data": [
    {
      "id": "1",
      "name": "Era Locksmith",
      "key": "EraLoc2015"
    },
    {
      "id": "2",
      "name": "Mac Garage Door",
      "key": "MacGdr2015"
    }
  ]
}

我正在扩展 ArrayAdapter<....> 并实现 Filterable

CompanyListAdapter.java:

    public class CompanyListAdapter extends ArrayAdapter<Company> implements Filterable {

    private Context context;
    ArrayList<Company> products;
    SharedPreference sharedPreference;

    private ArrayList<Company> filteredCompanies;
    private CompanyFilter mFilter = new CompanyFilter();

    public CompanyListAdapter(Context context, ArrayList<Company> products) {
        super(context, R.layout.company_list_item, products);
        this.context = context;
        this.products = products;
        sharedPreference = new SharedPreference();
    }

    @Override
    public Filter getFilter() {
        return mFilter;
    }

    private class ViewHolder {
        TextView productNameTxt;
        TextView productKeyTxt;
        ImageView favoriteImg;
    }

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

    @Override
    public Company getItem(int position) {
        return products.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = null;
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.company_list_item, null);
            holder = new ViewHolder();
            holder.productNameTxt = (TextView) convertView
                    .findViewById(R.id.txt_pdt_name);
            holder.productKeyTxt = (TextView) convertView
                    .findViewById(R.id.txt_pdt_price);
            holder.favoriteImg = (ImageView) convertView
                    .findViewById(R.id.imgbtn_favorite);

            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        Company product = (Company) getItem(position);
        holder.productNameTxt.setText(product.getName());
        holder.productKeyTxt.setText(product.getPrice() + "");

        /*If a product exists in shared preferences then set heart_red drawable
         * and set a tag*/
        if (checkFavoriteItem(product)) {
            holder.favoriteImg.setImageResource(R.drawable.heart_red);
            holder.favoriteImg.setTag("red");
        } else {
            holder.favoriteImg.setImageResource(R.drawable.heart_grey);
            holder.favoriteImg.setTag("grey");
        }

        return convertView;
    }   

    /*Checks whether a particular product exists in SharedPreferences*/
    public boolean checkFavoriteItem(Company checkProduct) {
        boolean check = false;
        List<Company> favorites = sharedPreference.getFavorites(context);
        if (favorites != null) {
            for (Company product : favorites) {
                if (product.equals(checkProduct)) {
                    check = true;
                    break;
                }
            }
        }
        return check;
    }

    @Override
    public void add(Company product) {
        super.add(product);
        products.add(product);
        notifyDataSetChanged();
    }

    @Override
    public void remove(Company product) {
        super.remove(product);
        products.remove(product);
        notifyDataSetChanged();
    }

    private class CompanyFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {

            String filterString = constraint.toString().toLowerCase();
            FilterResults results = new FilterResults();

            final List<Company> list = products;

            int count = list.size();
            final ArrayList<Company> nlist = new ArrayList<Company>(count);

            Company filterableCompany;

            for (int i = 0; i < count; i++) {
                filterableCompany = list.get(i);
                if (filterableCompany.getKey().toLowerCase().contains(filterString)) {
                    nlist.add(filterableCompany);
                }
            }

            results.values = nlist;
            results.count = nlist.size();

            return results;
        }

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

}

使用EditText接受"key"

CompanyListActivity.java:

EditText filterList = (EditText) view.findViewById(R.id.editKey);
        filterList.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                // TODO Auto-generated method stub
                productListAdapter.getFilter().filter(s.toString());
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable s) {
                // TODO Auto-generated method stub

            }
        });

我正在使用@Leigh 提供的代码

【问题讨论】:

标签: android json arraylist filter


【解决方案1】:

为什么不使用implement Filterable? 试试这样的:

让你的适配器类看起来像这样:

public class CompanyListAdapter extends ArrayAdapter<Company> implements Filterable {

    private List<Company> companies;
    private List<Company> filteredCompanies;
    private CompanyFilter mFilter = new CompanyFilter();

    private Context context;
    SharedPreference sharedPreference;

    public CompanyListAdapter(Context context, ArrayList<Company> products) {
        super(context, R.layout.company_list_item, products);
        this.context = context;
        this.products = products;
        this.filteredCompanies = products;
        sharedPreference = new SharedPreference();
    }

    @Override
    public int getCount() {
        return filteredCompanies == null 0 : filteredCompanies.size();
    }

    @Override
    public Company getItem(int position) {
        return filteredCompanies.get(position);
    }

    @Override
        public Filter getFilter() {
        return mFilter;
    }
}

接下来继续创建 CompanyFilter:

private class CompanyFilter extends Filter {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        String filterString = constraint.toString().toLowerCase();
        FilterResults results = new FilterResults();

        final List<Company> list = companies;

        int count = list.size();
        final ArrayList<Company> nlist = new ArrayList<Company>(count);

        Company filterableCompany;

        for (int i = 0; i < count; i++) {
            filterableCompany = list.get(i);
            if (filterableCompany.getName().toLowerCase().contains(filterString)) {
                nlist.add(filterableCompany);
            }
        }

        results.values = nlist;
        results.count = nlist.size();

        return results;
    }

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

通过这种方式,您可以将过滤器应用于任意数量的字段。请注意,在我的示例中,我使用 company 类的 getName() 来应用过滤器。

编辑: 要在Activity / Fragment 中使用它进行搜索,您可以将TextWatcher 添加到您的EditText 并应用过滤器onTextChanged。像这样的:

txtSearch.addTextChangedListener(new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        adapter.getFilter().filter(s.toString());
    }
});

【讨论】:

  • 很棒的代码,但有点混淆了这段代码是如何连接到我的 EditText 的?
  • @Sun 查看我的编辑,它为您提供了一个示例,说明如何对适配器使用过滤器。
  • @Sun 查看我的更新,您现在应该使用filteredCompanies 而不是companies(以前的products)。你也应该在你的getView() 中使用filteredCompanies
  • 一旦我的数据被解析,我想缓存以备不时之需,即使互联网不可用,每当有新数据出现时,我都想获取>缓存 - 你能帮我吗?
  • @Sun 我可以帮忙,但您可能应该提出一个新问题,因为这是一个不相关的问题。
【解决方案2】:

你需要让你的适配器像这样实现Filterable

class CustomAdapter extends BaseAdapter implements Filterable {
    @Override
        public Filter getFilter() { ...}

试着看看这个答案:
List View Filter Android

【讨论】:

    猜你喜欢
    • 2018-08-23
    • 2018-11-28
    • 2016-08-04
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-02
    • 1970-01-01
    相关资源
    最近更新 更多