使用ArrayAdapter过滤ListView而不重写getFilter方法 [英] Filtering a ListView using an ArrayAdapter without overriding getFilter method

查看:78
本文介绍了使用ArrayAdapter过滤ListView而不重写getFilter方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此Stackoverflow answer 中,指示可以在ListView中完成过滤,而不必覆盖ArrayAdaptergetFilter方法,而可以在POJO类中实现toString.

In this Stackoverflow answer, it is indicated that filtering can be accomplished in a ListView without overriding the getFilter method of the ArrayAdapter and instead implementing toString in the POJO class.

我尝试实现它,但是过滤器无法正常工作.尽管ListView会过滤,但不会在数组中显示正确的项目.因此,例如,如果过滤器与array中的单行匹配,则ListView中将显示一项,但显示的是错误的项目.在这种情况下,始终显示数组的第一项,而不是实际上与输入的搜索文本匹配的项.

I have tried implementing it, but the filtering is not working correctly. Although the ListView does filter, it doesn't show the correct items in the array. So, for example, if the filter matches a single row in the array then one item is shown in the ListView, but it is the wrong item that is shown. In this scenario, the first item of the array is always shown and not the item that actually matches the entered search text.

这是我的ArrayAdapter的代码:

public class TitleListingArrayAdapter extends ArrayAdapter<Title> {

    private List<Title> items;
    private Context context;

    public TitleListingArrayAdapter(Context context, int textViewResourceId, List<Title> items) {
        super(context, textViewResourceId, items);
        this.items = items;
        this.context = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
    {
        View view = convertView;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.titlelisting_single_row, null);
        }
        Title item = items.get(position);
        if (item!= null) {
            TextView titleView = (TextView) view.findViewById(R.id.title);            
            if (titleView != null) {
                titleView.setText(item.getName());
            }
            TextView yearView = (TextView) view.findViewById(R.id.year);
            if (yearView != null) {
                yearView.setText(String.valueOf(item.getYear())+", ");
            }
            TextView genreView = (TextView) view.findViewById(R.id.genre);
            if (genreView != null) {
                genreView.setText(item.getGenre());
            }
            TextView authorView = (TextView) view.findViewById(R.id.author);
            if (authorView != null) {
                authorView.setText(item.getAuthor());
            }
            RatingBar ratingView = (RatingBar) view.findViewById(R.id.rating);
            if (ratingView != null) {
                ratingView.setRating(item.getRating());
            }
            ImageView iconView = (ImageView) view.findViewById(R.id.list_image);
            iconView.setImageResource(lookupResourceId(context, item.getID()));            
        }
        return view;
    }

    private int lookupResourceId(Context context, String id) {
        String resourceName =  "thumb_"+id;
        return context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName());
    }
}

这是我的Activity代码的相关部分:

Here is the relevant section of my Activity code:

 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.listing);
    databaseHandler = new DatabaseHandler(this);
    listView = (ListView) findViewById(R.id.list);
    List<Title> titles = databaseHandler.getAllTitles();
    adapter = new TitleListingArrayAdapter(this, R.id.list, titles);
    listView.setAdapter(adapter);
    filterText = (EditText) findViewById(R.id.filter);
    filterText.addTextChangedListener(filterTextWatcher);
}

private TextWatcher filterTextWatcher = new TextWatcher() {
    public void afterTextChanged(Editable s) {}
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        adapter.getFilter().filter(s.toString().toLowerCase());
    }
};

Title POJO类实现toString的方法如下:

The Title POJO class implements toString as follows:

@Override
public String toString() {
    String name = this.getName() == null ? "" : this.getName().toLowerCase();
    String year = this.getYear() == null ? "" : this.getYear().toString();
    String genre = this.getGenre() == null ? "" : this.getGenre().toLowerCase();
    return name + " " +year+ " "+ genre;
}

有人知道为什么过滤无法正常工作以及如何解决吗?

Does anyone have any idea why the filtering is not working correctly and how I could fix it?

推荐答案

以下问题处理与我遇到的完全相同的问题.这个问题还提供了一个示例,说明了过滤正在执行的操作,通过未在列表中显示正确的项目来显示正确的数量个项目.

The following question deals with exactly the same issue that I encountered. This question also gives an example of what the filtering is doing, showing the correct number of items by not showing the correct items in the list.

所以看来 answer 是错误的,尽管被投票了六次.我完全不使用ArrayAdaptergetFilter方法来解决此问题.相反,我在TextWatcher实例中创建一个新的ArrayAdapter,如下所示:

So it seems that this answer is wrong, despite being upvoted six times. I resolved this by not making use of the getFilter method of the ArrayAdapter at all. Rather, I create a new ArrayAdapter in my TextWatcher instance, as follows:

private TextWatcher filterTextWatcher = new TextWatcher() {
     public void afterTextChanged(Editable s) {}
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         if (!s.toString().equals("")) {
              List<Title> filteredTitles = new ArrayList<Title>();
              for (int i=0; i<titles.size(); i++) {
                   if (titles.get(i).toString().contains(s)) {
                       filteredTitles.add(titles.get(i));                   
                   }            
              }
              adapter = new TitleListingArrayAdapter(TitleListingActivity.this, R.id.list, filteredTitles);
              listView.setAdapter(adapter);
         }
         else {
              adapter = new TitleListingArrayAdapter(TitleListingActivity.this, R.id.list, titles);
              listView.setAdapter(adapter);             
         }
    }
};

请注意,我还将声明List<Title> titlesonCreate中移出,并使其成为了我的Activity类的成员变量,以便可以在filterTextWatcheronTextChanged方法中对其进行访问.

Note that I also moved the declaration List<Title> titles out of onCreate and made it a member variable of my Activity class so that it is accessible inside the onTextChanged method of filterTextWatcher.

这篇关于使用ArrayAdapter过滤ListView而不重写getFilter方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆