自定义ArrayAdapter上的getFilter()无法正常运行

时间:2018-11-10 17:16:24

标签: java android custom-adapter android-filterable android-filter

我正在使用自定义ArrayAdapter 存储用户信息,例如sammy,robert,lizie都是一个User对象,并且我正在使用用户类型 ArrayList 存储所有用户对象 ArrayList

并且因为它不是字符串或int(ArrayList),所以默认的 getFilter 不起作用,我已经完成了研究,但确实使 getFilter 感到困惑>方法有效,所以我可以修改自己。

我要基于name

User class属性来实现搜索

我知道我必须在 CustomAdapter 类中实现 Filterable 接口,但是 getFilter 确实不直观。

这是我的CustomAdapter

class CustomArrayAdapter extends ArrayAdapter<User>  implements Filterable {


    CustomArrayAdapter(@NonNull Context context, ArrayList<User> users) {
        super(context, 0, users);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        User innserUser = getItem(position);

        if (convertView == null){

            convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_layout, parent, false);

        }

        TextView username = (TextView) convertView.findViewById(R.id.userNameContact);
        TextView userNumber = (TextView) convertView.findViewById(R.id.userNumberContact);
        ImageView userImage = (ImageView) convertView.findViewById(R.id.userImageContact);

        try {
            if(innserUser != null) {
                username.setText(innserUser.name);
                userNumber.setText(innserUser.number);
                userImage.setImageBitmap(innserUser.imageBitmap);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return convertView;

    }


}

这是这里的用户类别,没什么特别的

import android.graphics.Bitmap;

public class User {

    String id, name, number;
    Bitmap imageBitmap;

    User(String id, String name, String number, Bitmap imageBitmap){

        this.id = id;
        this.name = name;
        this.number = number;
        this.imageBitmap = imageBitmap;

    }
}

我从许多线程中捆绑了许多 getFilter 的变体,但它们都不适合我,而那些很好解释的是BaseAdapter而不是ArrayAdapter

我已经尝试过question,而我已经尝试过question,但对我不起作用。

我是android开发领域的新手,这似乎特别不直观。 任何建议将不胜感激,谢谢。

编辑1 :在回答 jitesh mohite 之后,感谢您重播 jitesh mohite

class CustomArrayAdapter extends ArrayAdapter<User>  implements Filterable {


    ArrayList<User> users;

    CustomArrayAdapter(@NonNull Context context, ArrayList<User> users) {
        super(context, 0, users);
        this.users = users;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        User innserUser = getItem(position);

        if (convertView == null){

            convertView = LayoutInflater.from(getContext()).inflate(R.layout.row_layout, parent, false);

        }

        TextView username = (TextView) convertView.findViewById(R.id.userNameContact);
        TextView userNumber = (TextView) convertView.findViewById(R.id.userNumberContact);
        ImageView userImage = (ImageView) convertView.findViewById(R.id.userImageContact);

        try {
            if(innserUser != null) {
                username.setText(innserUser.name);
                userNumber.setText(innserUser.number);
                userImage.setImageBitmap(innserUser.imageBitmap);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return convertView;

    }


    Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            ArrayList<User> tempList=new ArrayList<User>();
            // Add the filter code here
            if(constraint != null && users != null) {
                int length= users.size();
                int i=0;
                while(i<length){
                    User item= users.get(i);
                    //do whatever you wanna do here
                    //adding result set output array

                    //item.name is user.name cause i want to search on name
                    if(item.name.toLowerCase().contains(constraint.toString().toLowerCase()) ) { // Add check here, and fill the tempList which shows as a result

                        tempList.add(item);
                    }

                    i++;
                }
                //following two lines is very important
                //as publish result can only take FilterResults users
                filterResults.values = tempList;
                filterResults.count = tempList.size();
            }
            return filterResults;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence contraint, FilterResults results) {
            users = (ArrayList<User>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }
    };

    @Override
    public Filter getFilter() {
        return myFilter;
    }


}

搜索仍然无法在自定义适配器上进行,我仍然认为自己做错了。

在这里我在搜索栏中输入了一些内容,但没有进行过滤

enter image description here

,如果您想查看搜索栏代码,它与通常的没什么不同

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();

    inflater.inflate(R.menu.search_box, menu);

    MenuItem item = menu.findItem(R.id.app_bar_search);

    SearchView searchView = (SearchView)item.getActionView();

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            customArrayAdapter.getFilter().filter(newText);

            return false;
        }
    });


    return true;



}

2 个答案:

答案 0 :(得分:1)

Filter myFilter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
         FilterResults filterResults = new FilterResults();   
         ArrayList<User> tempList=new ArrayList<User>();
         // Add the filter code here
         if(constraint != null && users!=null) {
             int length= users.size();
             int i=0;
                while(i<length){
                    User item= users.get(i);
                    //do whatever you wanna do here
                    //adding result set output array    
                    if()  {  // Add check here, and fill the tempList which shows as a result

                    tempList.add(item);
                  }

                    i++;
                }
                //following two lines is very important
                //as publish result can only take FilterResults users
                filterResults.values = tempList;
                filterResults.count = tempList.size();
          }
          return filterResults;
      }

      @SuppressWarnings("unchecked")
      @Override
      protected void publishResults(CharSequence contraint, FilterResults results) {
          users = (ArrayList<User>) results.values;
          if (results.count > 0) {
           notifyDataSetChanged();
          } else {
              notifyDataSetInvalidated();
          }  
      }
     };

最后,重写此方法并返回过滤器实例。

@Override
     public Filter getFilter() {
        return myFilter;
    }

有关更多参考,请参见https://gist.github.com/tobiasschuerg/3554252

答案 1 :(得分:1)

ArrayAdapter的内置Filter使用来自模型类的toString()返回(即其类型参数)来执行其过滤比较。如果您能够覆盖Filter的{​​{1}}方法以返回要比较的内容,则不一定需要自定义的User实现,只要它的过滤算法适合您情况(请参见下文)。在这种情况下:

toString()

要确切了解该算法是什么,@Override public String toString() { return name; } 的默认过滤如下:

过滤器ArrayAdapter首先转换为小写。然后,遍历数据集,将每个值的String返回值转换为小写字母,并检查其是否为toString()过滤器startsWith()。如果是这样,它将被添加到结果集中。如果不是,则执行第二次检查,从而将值的小写字母String在空格(String)上分割,然后再次使用" "将其中的每个值与过滤器进行比较。基本上,它首先检查整个内容是否以过滤器文本开头,然后在必要时检查每个单词。

如果这是一个合适的过滤器,那么到目前为止,该解决方案是最简单的。