簡單的說就是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;
}
}
<?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>