作者Y78 (Y78)
看板AndroidDev
标题[分享] 自订ListView的搜寻功能
时间Thu Dec 27 12:03:58 2012
像是内建的通讯录那样
有一个editText可以输入,当你输入a的时候
底下的list就自动跑出a开头的联络人名单
对於普通的ArrayAdapter来说 这件事情非常简单可以达成
最近研究了一下自订的ListView如何达成这件事
跟大家分享一下心得
建议先看过普通的ListView如何做出这样的东西再来看这篇文章
http://tinyurl.com/borkabs
由於这篇直接从上一篇的code拿来修改 所以建议先看过上一篇
首先先在你的activity加入一个editText
EditText edt;
edt = (EditText) findViewById(R.id.EditText01);
然後记得设定ListView
listV.setTextFilterEnabled(true);
接着就像普通的搜寻那样 建立一个TextWatcher
edt.addTextChangedListener(new TextWatcher(){
@Override
public void onTextChanged( CharSequence arg0, int arg1, int arg2, int
arg3){}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int
arg3){}
@Override
public void afterTextChanged(Editable arg0)
{
Main.this.adapter.getFilter().filter(arg0);
}
});
接着我们只要修改上一篇中写得MyAdapter.java就可以了
原本是
public class MyAdapter extends BaseAdapter
由於我们要做filter的功能 所以需要
public class MyAdapter extends BaseAdapter implements Filterable
接着宣告
private List<Movie> mOriginalValues;
private MyFilter filter;
mOriginalValues是拿来保存你最原本传进来的list
MyFilter这之後会讲到
然後加入一个method
@Override
public Filter getFilter() {
if (filter == null){
filter = new MyFilter();
}
return filter;
}
接着就是开始本篇文章的重点了
就是MyFilter的部份
private class MyFilter extends Filter{
有两个方法需要继承
protected FilterResults performFiltering(CharSequence constraint)
protected void publishResults(CharSequence constraint, FilterResults results)
performFiltering是实际需要做筛选的code 好像是在不同的thread进行
publishResults则是用来把筛选结果publish出去的函式
先来看後者
@Override
protected void publishResults(CharSequence constraint, FilterResults results)
{
movies = (ArrayList<Movie>)results.values;
if(results.count>0){
notifyDataSetChanged();
}
else{
notifyDataSetInvalidated();
}
}
记得吗? movies是我们存放资料的List
而results.values就是筛选过後的结果
我们让movies = results.values
notifyDataSetChanged之後会自动更新List
再来是
protected FilterResults performFiltering(CharSequence constraint) {
constraint = constraint.toString();
FilterResults result = new FilterResults();
if (mOriginalValues == null) {
synchronized (this) {
mOriginalValues = new ArrayList<Movie>(movies);
}
}
先判断mOriginalValues是不是null
如果是的话把movies的值整个复制过去
第一次执行的话一定是null 所以mOriginalValues就会是一开始的值
if(constraint != null && constraint.toString().length() > 0){
ArrayList<Movie> filteredItems = new ArrayList<Movie>();
for(int i = 0, l = mOriginalValues.size(); i < l; i++){
Movie m = mOriginalValues.get(i);
if(m.getName().contains(constraint)){
filteredItems.add(m);
}
}
result.count = filteredItems.size();
result.values = filteredItems;
}else{
synchronized(this){
ArrayList<Movie> list = new ArrayList<Movie>(mOriginalValues);
result.values = list;
result.count = list.size();
}
}
return result;
先看else的部份
会执行到这边就表示传进来的参数(要搜寻的字串)是不合格的
所以就直接把一开始的mOriginalValues return回去
至於另一个部份就是搜寻整个mOriginalValues
看看是否包含要搜寻的字串
最值得注意的是
Movie m = mOriginalValues.get(i);
if(m.getName().contains(constraint)){
filteredItems.add(m);
}
这边换成你自己的自订class
比如说我有一个class叫做Userinfo 要搜寻联络人
那就
Userinfo u = mOriginalValues.get(i)
if(u.getName().contains(constraint)){
filteredItems.add(u)
}
总之filteredItems就是你最後要显示的资料
完整的code在这边
http://pastebin.com/pdPeAC7K
好处就是你刚刚写得有关自订的ListView的code完全不需要修改
只需要加入一些东西就可以达成搜寻的功能
参考资料:
http://blog.csdn.net/jiahui524/article/details/7802033
http://tinyurl.com/cu3pst4
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.135.198.74
1F:推 tomap41017:这边的API跟Loader没同步蛮困扰得XD 12/29 01:01