通过EditText中的输入,实现ListView过滤,主要是让adapter实现Filterable接口。可以参考SimpleAdapter的实现方式。
至于拼音过滤,在google code中有一个pinyin4android的开源项目,已经实现了对中文拼音的匹配。
效果图:
定义一个UserAdapter,对user的name字段进行过滤:
public class UserAdapter extends BaseAdapter implements Filterable{
private List<User> users;
public Context mContext;
private LayoutInflater mInflater;
private FilterDemo mFilter;
private ArrayList<User> mDisplayData;
//记录索引
private ArrayList<FilterIndex> mFilterIndexs;
public UserAdapter(Context context, List<User> users)
{
super();
mContext = context;
this.users = users;
mDisplayData = (ArrayList<User>) users;
mFilterIndexs = new ArrayList<FilterIndex>();
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount()
{
// TODO Auto-generated method stub
return mDisplayData.size();
}
@Override
public Object getItem(int position)
{
// TODO Auto-generated method stub
return mDisplayData.get(position);
}
@Override
public long getItemId(int position)
{
// TODO Auto-generated method stub
return mDisplayData.get(position).getId();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent)
{
// TODO Auto-generated method stub
if (convertView == null)
convertView = mInflater.inflate(R.layout.item, null);
ViewHolder holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.age = (TextView) convertView.findViewById(R.id.age);
User user = mDisplayData.get(position);
SpannableStringBuilder ss=new SpannableStringBuilder(user.getName());
if(!mFilterIndexs.isEmpty())
ss.setSpan(new ForegroundColorSpan(Color.RED),mFilterIndexs.get(position).getBegin(),mFilterIndexs.get(position).getEnd(),Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
holder.name.setText(ss);
holder.age.setText(user.getAge()+"");
return convertView;
}
static class ViewHolder
{
TextView name;
TextView age;
}
@Override
public Filter getFilter()
{
// TODO Auto-generated method stub
if (mFilter == null) {
mFilter = new FilterDemo();
}
return mFilter;
}
private class FilterDemo extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
ArrayList<String> mData = new ArrayList<String>();
mFilterIndexs.clear();
for(int i = 0; i < users.size(); i ++){
String name = users.get(i).getName();
mData.add(name);
}
if (prefix == null || prefix.length() == 0) {
results.values = mData;
results.count = mData.size();
} else {
String prefixString = prefix.toString();
int count = mData.size();
ArrayList<String> newValues = new ArrayList<String>(count);
for (int j = 0; j < count; j++) {
String s = mData.get(j);
//
String s1 = getPinYinHeadChar(s);
if(s1.contains(prefixString))
{
getFilterIndex(s1,prefixString);
newValues.add(s);
}else
if(s.contains(prefixString))
{
getFilterIndex(s,prefixString);
newValues.add(s);
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mDisplayData = new ArrayList<User>(results.count);
for(String username:(ArrayList<String>)results.values)
{
for(User userInfo:users)
{
if(userInfo.getName().equals(username)){
mDisplayData.add(userInfo);
}
}
}
notifyDataSetChanged();
}
//提取汉字的首字母
private String getPinYinHeadChar(String str) {
StringBuilder convert = new StringBuilder();
int length = str.length();
for (int j = 0; j < length; j++) {
char word = str.charAt(j);
try {
String pinyinArray = PinyinUtil.toPinyin(mContext, word);
if (pinyinArray != null) {
convert.append(pinyinArray.charAt(0));
} else {
convert.append(word);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return convert.toString();
}
/**
* 获取指定字符的开始与结束的位置
*/
private void getFilterIndex(String father,String child)
{
int start = father.indexOf(child);
int end = start+child.length();
FilterIndex filterIndex = new FilterIndex(start,end);
mFilterIndexs.add(filterIndex);
}
}
class FilterIndex
{
private int begin;
private int end;
public FilterIndex(int begin,int end)
{
this.begin = begin;
this.end = end;
}
public int getBegin() {
return begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
}
}
然后再Activity中使用该adapter,为EditText添加addTextChangedListener:
private ListView mListView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initComponent();
}
private void initComponent() {
// TODO Auto-generated method stub
EditText edit = (EditText) findViewById(R.id.edit);
mListView = (ListView) findViewById(R.id.list_view);
List<User> users = new ArrayList<User>();
users.add(0, new User("zhangsan", 20));
users.add(1, new User("lishi", 21));
users.add(1, new User("wangwu", 21));
users.add(1, new User("zhaoliu", 21));
users.add(1, new User("xiaoming", 21));
users.add(1, new User("daming", 21));
final UserAdapter adapter = new UserAdapter(this, users);
mListView.setAdapter(adapter);
edit.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
adapter.getFilter().filter(s);
}
});
}