Android 数据过滤器:Filter

类图:

Android 数据过滤器:Filter

通常可以将SearchView和ListView结合,实现数据的搜索和过滤。

1.监听SearchView,SearchView.setOnQueryTextListener(OnQueryTextListener listener);

2.开启ListView的过滤功能,listView.setTextFilterEnabled(true)。必须开启,否则不会过滤;

3..当SearchView接收到输入事件后,调用ListView.setFilterText(filterText)方法,该方法会通过Adapter得到Filter,然后调用Filter.filter(filterText):

  1. public void setFilterText(String filterText) {
  2. // TODO: Should we check for acceptFilter()?
  3. if (mTextFilterEnabled && !TextUtils.isEmpty(filterText)) {
  4. createTextFilter(false);
  5. // This is going to call our listener onTextChanged, but we might not
  6. // be ready to bring up a window yet
  7. mTextFilter.setText(filterText);
  8. mTextFilter.setSelection(filterText.length());
  9. if (mAdapter instanceof Filterable) {
  10. // if mPopup is non-null, then onTextChanged will do the filtering
  11. if (mPopup == null) {
  12. Filter f = ((Filterable) mAdapter).getFilter();
  13. f.filter(filterText);
  14. }
  15. // Set filtered to true so we will display the filter window when our main
  16. // window is ready
  17. mFiltered = true;
  18. mDataSetObserver.clearSavedState();
  19. }
  20. }
  21. }

4.Filter.filter(filterText)方法最终会调用Filter.performFiltering(filterText)和Filter.publishResults(CharSequence filterText, FilterResults results)。performFiltering(filterText)方法完成过滤处理并且返回结果FilterResults,而publishResults(CharSequence filterText, FilterResults results)则根据返回的结果进行相应的处理。

5.Filter.publishResults(CharSequence filterText, FilterResults results)调用了BaseAdapter.notifyDataSetChanged()方法,该方法用于当Adapter的数据发生变化时,通知UI主线程根据新的数据绘制界面:

  1. @Override
  2. protected void publishResults(CharSequence constraint, FilterResults results) {
  3. //noinspection unchecked
  4. mObjects = (List<T>) results.values;
  5. if (results.count > 0) {
  6. notifyDataSetChanged();
  7. } else {
  8. notifyDataSetInvalidated();
  9. }
  10. }

数据过滤就这样完成了。

下面给出例子。

布局文件filter_activity.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical" >
  6. <SearchView
  7. android:id="@+id/searchView1"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content" >
  10. </SearchView>
  11. <ListView
  12. android:id="@+id/listView1"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content" >
  15. </ListView>
  16. </LinearLayout>

类文件MainActivity.java:

  1. package com.zzj.ui.filterdemo;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.widget.ArrayAdapter;
  5. import android.widget.ListView;
  6. import android.widget.SearchView;
  7. import android.widget.SearchView.OnQueryTextListener;
  8. import com.zzj.ui.R;
  9. public class MainActivity extends Activity implements OnQueryTextListener {
  10. private ListView listView;
  11. @Override
  12. protected void onCreate(Bundle savedInstanceState) {
  13. super.onCreate(savedInstanceState);
  14. setContentView(R.layout.filter_activity);
  15. SearchView searchView = (SearchView) findViewById(R.id.searchView1);
  16. searchView.setOnQueryTextListener(this);
  17. searchView.setSubmitButtonEnabled(false);
  18. searchView.setIconifiedByDefault(false);
  19. listView = (ListView) findViewById(R.id.listView1);
  20. ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
  21. android.R.layout.simple_list_item_1, new String[] { "Bei jing",
  22. "Shang hai", "Chang sha", "Chang chun", "Nan jing",
  23. "Dong jing", "Ji nan", "Qing dao", "Xiang tan",
  24. "Zhu zhou", "Heng yang" });
  25. listView.setAdapter(adapter);
  26. // 开启过滤功能
  27. listView.setTextFilterEnabled(true);
  28. }
  29. @Override
  30. public boolean onQueryTextSubmit(String query) {
  31. return false;
  32. }
  33. @Override
  34. public boolean onQueryTextChange(String newText) {
  35. if (newText == null || newText.length() == 0) {
  36. listView.clearTextFilter();
  37. } else {
  38. listView.setFilterText(newText);
  39. }
  40. return true;
  41. }
  42. }

效果图:

Android 数据过滤器:Filter

如图所示,弹出了一个浮动框,这是listView.setFilterText(filterText)弹出来的。如果不想要这个浮动框,可以先获取Filter,然后调用Filter.filter(filterText)。

修改SearchView的监听函数如下:

  1. @Override
  2. public boolean onQueryTextChange(String newText) {
  3. ListAdapter adapter = listView.getAdapter();
  4. if (adapter instanceof Filterable) {
  5. Filter filter = ((Filterable) adapter).getFilter();
  6. if (newText == null || newText.length() == 0) {
  7. filter.filter(null);
  8. } else {
  9. filter.filter(newText);
  10. }
  11. }
  12. return true;
  13. }

使用这种方法不需要开启ListView的过滤功能。效果如下:

Android 数据过滤器:Filter

上面使用的是ArrayAdapter的过滤功能,我们也可以继承BaseAdapter,然后实现Filterable接口,定义自己的过滤器。

上一篇:常用sql命令


下一篇:现代编译原理——第二章:语法分析之LL(K)