Android实现Filterable通过输入文本框实现联系人自动筛选
相信大家一定在见过手机通讯录的一个情景就是使用在选人的时候输入文本框里的数据就能自动筛选。今天也受一网友邀请,所以还是整理了一下这块的知识点,现在与大家共享一下,有什么疑惑的可以与我交流。实现的效果如下图。
其实实现这样的效果相信大家一定对另外一个控件不陌生那就AutoCompleteTextview,看一下这个控件的源代码也许就能找到你需要的答案。这里的核心就是一个Filterable。至于Filterable的介绍和做什么用的大家就可以自行上网查找相关知识,其中有两个重要的方法
方法名 |
作用 |
protected FilterResults performFiltering(CharSequence prefix) |
在这个方法里执行过滤方法 |
protectedvoidpublishResults(CharSequence constraint, FilterResults results) |
在这个方法里发布筛选过后得到的数据同时更新Adapter更新 |
理解这点知识那么就看核心代码吧,这里就是重写BaseAdapter然后实现Filterable
- publicclassUserAdapterextendsBaseAdapterimplementsFilterable{
- privateMyFiltermyFilter;
- privateList<UserInfo>userInfos;
- privateContextcontext;
- privateArrayList<UserInfo>mOriginalValues;
- privatefinalObjectmLock=newObject();
- publicUserAdapter(Contextcontext,List<UserInfo>userInfos){
- this.context=context;
- this.userInfos=userInfos;
- }
- @Override
- publicintgetCount(){
- //TODOAuto-generatedmethodstub
- returnuserInfos.size();
- }
- @Override
- publicObjectgetItem(intarg0){
- //TODOAuto-generatedmethodstub
- returnuserInfos.get(arg0);
- }
- @Override
- publiclonggetItemId(intposition){
- //TODOAuto-generatedmethodstub
- returnposition;
- }
- @Override
- publicViewgetView(intposition,ViewconvertView,ViewGroupparent){
- Viewview=convertView;
- ViewHolderholder;
- if(view==null){
- view=LayoutInflater.from(context).inflate(R.layout.list_item,
- null);
- holder=newViewHolder();
- holder.tv_nick=(TextView)view.findViewById(R.id.tv_nick);
- holder.tv_mobile=(TextView)view.findViewById(R.id.tv_mobile);
- view.setTag(holder);
- }else{
- holder=(ViewHolder)view.getTag();
- }
- holder.tv_nick.setText(userInfos.get(position).getUsername());
- holder.tv_mobile.setText(userInfos.get(position).getPhonenum());
- returnview;
- }
- staticclassViewHolder{
- TextViewtv_nick;
- TextViewtv_mobile;
- }
- @Override
- publicFiltergetFilter(){
- if(myFilter==null){
- myFilter=newMyFilter();
- }
- returnmyFilter;
- }
- classMyFilterextendsFilter{
- @Override
- protectedFilterResultsperformFiltering(CharSequenceprefix){
- //持有过滤操作完成之后的数据。该数据包括过滤操作之后的数据的值以及数量。count:数量values包含过滤操作之后的数据的值
- FilterResultsresults=newFilterResults();
- if(mOriginalValues==null){
- synchronized(mLock){
- //将list的用户集合转换给这个原始数据的ArrayList
- mOriginalValues=newArrayList<UserInfo>(userInfos);
- }
- }
- if(prefix==null||prefix.length()==0){
- synchronized(mLock){
- ArrayList<UserInfo>list=newArrayList<UserInfo>(
- mOriginalValues);
- results.values=list;
- results.count=list.size();
- }
- }else{
- //做正式的筛选
- StringprefixString=prefix.toString().toLowerCase();
- //声明一个临时的集合对象将原始数据赋给这个临时变量
- finalArrayList<UserInfo>values=mOriginalValues;
- finalintcount=values.size();
- //新的集合对象
- finalArrayList<UserInfo>newValues=newArrayList<UserInfo>(
- count);
- for(inti=0;i<count;i++){
- //如果姓名的前缀相符或者电话相符就添加到新的集合
- finalUserInfovalue=(UserInfo)values.get(i);
- Log.i("coder","PinyinUtils.getAlpha(value.getUsername())"
- +PinyinUtils.getAlpha(value.getUsername()));
- if(PinyinUtils.getAlpha(value.getUsername()).startsWith(
- prefixString)
- ||value.getPhonenum().startsWith(prefixString)||value.getUsername().startsWith(prefixString)){
- newValues.add(value);
- }
- }
- //然后将这个新的集合数据赋给FilterResults对象
- results.values=newValues;
- results.count=newValues.size();
- }
- returnresults;
- }
- @Override
- protectedvoidpublishResults(CharSequenceconstraint,
- FilterResultsresults){
- //重新将与适配器相关联的List重赋值一下
- userInfos=(List<UserInfo>)results.values;
- if(results.count>0){
- notifyDataSetChanged();
- }else{
- notifyDataSetInvalidated();
- }
- }
- }
- }
具体有看不懂的代码可以看注释或者加我QQ
最后再看一下是怎么用的吧
- et_filter.addTextChangedListener(newTextWatcher(){
- @Override
- publicvoidonTextChanged(CharSequences,intstart,intbefore,
- intcount){
- adapter.getFilter().filter(et_filter.getText().toString());
- }
- @Override
- publicvoidbeforeTextChanged(CharSequences,intstart,intcount,
- intafter){
- //TODOAuto-generatedmethodstub
- }
- @Override
- publicvoidafterTextChanged(Editables){
- //TODOAuto-generatedmethodstub
- }
- });
好了这么一样的一个功能就如此简单的完成了,希望能对大家有所帮助了