Android 自定义过滤搜索框 filterable
简单的说就是ListView上面有一个SearchBox,然后searchbox里输入内容后对下面listview进行过滤。
涉及的控件:ListView必须有,EditText用来自定义SearchBox
大概就是这样:
先看这个有图片的EditText,实现方法有两个,一是用相对布局RelativeLayout + ImageView + EditText。
二是直接用EditText的一个属性DrawableLeft,简单的UI这个就可以实现了
所以这个Activity的布局就很简单,可以用ListActivity实现:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <EditText android:id="@+id/searchbox" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:drawableLeft="@drawable/searchbox" android:hint="Search" android:drawablePadding="5dp" android:singleLine="true" android:ems="10" > <requestFocus /> </EditText> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/searchbox"> </ListView> </RelativeLayout>
再说过滤功能:这个感觉不想搜索,就像是简单的过滤,如果涉及到去数据库取数据那个才是搜索了
用到了Filterable接口,Filter类
要让数据有过滤功能,我们需要在继承的BaseAdapter的基础上再实现Filterable接口的getFilter方法,同时在Adapter内部写一个继承Filter的内部类来完成过滤功能:
private class ListAdapter extends BaseAdapter implements Filterable { private List<Person> list; private Context context; private PersonFilter filter; public ListAdapter(List<Person> list, Context context) { this.list = list; this.context = context; } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null); } Person p = list.get(position); TextView firstname = (TextView)convertView.findViewById(R.id.firstname); TextView lastname = (TextView)convertView.findViewById(R.id.lastname); TextView age = (TextView)convertView.findViewById(R.id.age); firstname.setText(p.firstname); lastname.setText(p.lastname); age.setText(p.age + ""); return convertView; } @Override public Filter getFilter() { if (filter == null) { filter = new PersonFilter(list); } return filter; } private class PersonFilter extends Filter { private List<Person> original; public PersonFilter(List<Person> list) { this.original = list; } @Override protected FilterResults performFiltering(CharSequence constraint) { FilterResults results = new FilterResults(); if (constraint == null || constraint.length() == 0) { results.values = original; results.count = original.size(); } else { List<Person> mList = new ArrayList<Person>(); for (Person p: original) { if (p.firstname.toUpperCase().startsWith(constraint.toString().toUpperCase()) || p.lastname.toUpperCase().startsWith(constraint.toString().toUpperCase()) || new String(p.age + "").toUpperCase().startsWith(constraint.toString().toUpperCase())) { mList.add(p); } } results.values = mList; results.count = mList.size(); } return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { list = (List<Person>)results.values; notifyDataSetChanged(); } } }
Filter类中的两个方法看名字就是知道一个是执行过滤的,一个刷新listview数据展现结果的。其中我采用了前缀匹配,就是用输入的字符串和ListView里的所有Person的各个属性的前缀做比较。也可以用更加复杂的匹配,例如正则表达式。
关键在于EditText里的数据是如何传入的,要写一个TextWater,并且要让EditText注册一下这个监听器:
private TextWatcher filterTextWatcher = new TextWatcher() { @Override public void afterTextChanged(Editable s) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { listAdapter.getFilter().filter(s); //这里传入数据就可以了 } };
以上关键代码。非关键代码是Person类以及List_Item的布局:
private class Person { public String firstname; public String lastname; public int age; public Person(String firtname, String lastname, int age) { this.firstname = firtname; this.lastname = lastname; this.age = age; } }
List_Item布局:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/firstname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="Firstname" /> <TextView android:id="@+id/lastname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="Lastname" /> <TextView android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="Age" /> </LinearLayout>
/home/wangjianhua/Desktop/1365932013_4825.jpg