【问题标题】:Filtered ListView not updated过滤的 ListView 未更新
【发布时间】:2011-01-31 03:19:48
【问题描述】:

我有一个带有自定义适配器的 ListView,它扩展了 ArrayAdapter。它是 Artist 类型的 ArrayAdapter。

Artist 是一个非常小的类,它有一个名字和一个 ID。 Artist 类已覆盖 toString() 以仅返回名称。

我有一个 EditText。 EditText 有一个 TextChangeListener 我在我的适配器上调用 .getFilter().filter(chars, callback) 。

在 Filter.Filterlistener().onComplete() 回调中,我打印了计数,它看起来非常好。当我键入时,计数会减少。所以它接缝一切都像宣传的那样工作,但列表保持不变。我试图调用 artistAdapter.notifyDataSetChanged() 来强制列表重绘,但没有任何反应。 [见 2.)]

我现在正在修补好几天!我很绝望..希望有人可以看看我的代码并告诉我我做错了什么!

谢谢!

这是我所做的:

1.) 像这样定义一个 ListView 和一个 EditText:

<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_search_text"
    android:layout_width="fill_parent"
    android:layout_height="35dip"
    android:layout_below="@id/header">
</EditText>       
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/list_search"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
</ListView>

2.) 在活动 onCreate() 中设置我的 ListView:

private ListView listView = null;
private ArtistAdapter artistAdapter = null;

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

    artistAdapter = new ArtistAdapter(this, R.layout.row, list); // 'list' is an ArrayList<Artist>

    listView = (ListView) findViewById(R.id.list_search);
    listView.setAdapter(artistAdapter);
    listView.setFastScrollEnabled(true);
    listView.setTextFilterEnabled(true);

    listView.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int position, long id) {
            // do something
        }
    });

    EditText txtSearch = (EditText) findViewById(R.id.list_search_text);
    txtSearch.addTextChangedListener(new TextWatcher() {
        public void afterTextChanged(Editable arg0) { }

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

        public void onTextChanged(CharSequence chars, int start, int before, int count) {
            artistAdapter.getFilter().filter(chars, new Filter.FilterListener() {
                public void onFilterComplete(int count) {
                    Log.d(Config.LOG_TAG, "filter complete! count: " + count);
                    artistAdapter.notifyDataSetChanged();
                }
            });
        }
    });
}

3.) 简而言之,这是我的 ArtistAdapter。我添加了一个 remove() 和 add() 方法:

public class ArtistAdapter extends ArrayAdapter<Artist> implements SectionIndexer {
    private List<Artist> items;

    /* other stuff like overridden getView, getPositionForSection, getSectionForPosition and so on */

    @Override
    public void remove(Artist object) {
        super.remove(object);
        items.remove(object);
    }

    @Override
    public void add(Artist object) {
        super.add(object);
        items.add(object);
    }
}    

4.) 我的艺术家还覆盖了 toString():

public class Artist implements Comparable<Artist> {
    public String   uid;
    public String   name;

    public Artist(String id, String name) {
        this.uid = id;
        this.name = name;
    }

    public int compareTo(Artist another) {
        return this.name.compareToIgnoreCase(another.name);
    }

    @Override
    public String toString() {
        return this.name;
    }
}

【问题讨论】:

    标签: android listview filter android-arrayadapter


    【解决方案1】:

    我找到了解决方案。我从头重写了整个代码,发现了问题。

    在我的名为 ArtistAdapter 的自定义 ArrayAdapter 中(请参阅有问题的 3.),如果有一个 var 来存储项目: 私有列表项;

    当我想要获取当前项目时,在我重写的 getView() 中: items.getItem(位置) 现在我做一个: getItems(position) (因此该项目是从基类的存储中检索的,而不是我自己的),这似乎可以解决问题!

    这是我现在的 getView()(正在运行的版本):

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LinearLayout artistView;
        Artist art = getItem(position);
    
        if (convertView == null) {
            artistView = new LinearLayout(getContext());
            String inflater = Context.LAYOUT_INFLATER_SERVICE;
            LayoutInflater vi;
            vi = (LayoutInflater)getContext().getSystemService(inflater);
            vi.inflate(resId, artistView, true);
        } else {
            artistView = (LinearLayout) convertView;
        }
        TextView nameView = (TextView)artistView.findViewById(R.id.txt_name);
        TextView uidView = (TextView)artistView.findViewById(R.id.txt_uid);
        nameView.setText(art.name);
        uidView.setText(art.uid);
        return artistView;
    }
    

    噗,真是个烦人的bug……

    【讨论】:

    • 你好 Anton,我遇到了和你一样的问题。我尝试删除局部变量列表。但没有从listview 搜索或查找数据。我设置了getItem(position) 而不是items.get(position) 但问题没有解决。请提出解决此问题的任何步骤
    • @SBJ 您能否发布您的解决方案以便对其他人有所帮助?
    【解决方案2】:

    尝试使用 listView.setFilterText() 而不是适配器过滤器。

    【讨论】:

    • 我尝试使用 .setFilterText() 但没有任何反应。我查看了 .setFilterText():为了让它工作,适配器必须实现 Filterable 接口,而这个接口只定义了我在上面使用的 .getFilter() 方法。因此,您的解决方案与我的解决方案相同(或者更准确地说:它正在执行相同的操作,而不是与我的完全一样)还有其他想法吗?
    • 它是否在 FilterListener 中给出了正确的计数值?
    • 嗨,卡兰!是的,在 FilterListeners onFilterComplete() 我有正确的计数值!任何想法为什么 listView 没有得到更新?
    【解决方案3】:

    您必须重写 toString() 方法,才能返回要过滤的文本。

    【讨论】:

      猜你喜欢
      • 2012-09-15
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      相关资源
      最近更新 更多