为了账号安全,请及时绑定邮箱和手机立即绑定

自定义 ArrayAdapter 上的 getFilter() 不起作用

自定义 ArrayAdapter 上的 getFilter() 不起作用

青春有我 2022-01-12 10:07:07
我正在使用自定义 ArrayAdapter来存储用户信息,例如 sammy、robert、lizie 都是一个用户对象,我正在使用用户类型ArrayList将所有用户对象存储到ArrayList。而且因为它不是字符串或 int(ArrayList),所以默认的getFilter不起作用,我已经完成了我的研究,但是getFilter方法的工作原理确实令人困惑,所以我可以修改自己。我想实现基于 name属性形式的搜索User class我知道我必须在我的CustomAdapter类中实现Filterable接口,但是getFilter真的不直观。这是我的自定义适配器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我试过这个问题,我也试过这个问题,但对我不起作用。我是 android 开发领域的新手,这似乎特别不直观。任何建议将不胜感激,谢谢。
查看完整描述

2 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

ArrayAdapter的内置函数Filter使用toString()模型类的返回值(即其类型参数)来执行其过滤比较。Filter如果您能够覆盖UsertoString()方法以返回您想要比较的内容,则不一定需要自定义实现(前提是其过滤算法适合您的情况)。在这种情况下:

@Override
public String toString() {
    return name;
    }

为了明确该算法是什么,ArrayAdapter的默认过滤如下:

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

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


如果这不能满足您的需求,并且您确实需要自定义Filter实现,那么您不应该一ArrayAdapter开始就使用。ArrayAdapter维护private List原始和过滤集合的internal, s - 最初从构造函数调用中传递的集合填充 - 您无权访问这些。这就是为什么显示的自定义Filter尝试不起作用的原因,因为显示的项目计数和返回的项目getItem(position)来自该内部过滤器List,而不是内置的自定义过滤器Filter

在这种情况下,您应该直接进行子类化BaseAdapterList为原始集合和过滤集合维护自己的s。您可以使用ArrayAdapter's source作为指南。

确实,ArrayAdapter在选择Adapter扩展时通常是错误的选择。ArrayAdapter是专为单数,有些简单化的目标:将在平板String上的单个TextView在每个列表项。在某些情况下,子类化ArrayAdapter而不是BaseAdapter毫无意义和/或多余。例如:

  • 覆盖getView()而不使用View从调用返回的super.getView().

  • TextView无论出于何种原因,手动设置自己的文本。

  • 维护和使用您自己的收藏;即,数组,或Lists,或者你有什么。

在这些和某些其他情况下,可以说BaseAdapter从一开始就使用它会更好。使用ArrayAdapter比具有基本功能的单个文本项更复杂的任何内容会很快变得麻烦且容易出错,而且通常麻烦多于其价值。


最后,我要提到的ListView是,在撰写本文时,尽管尚未正式发布,但目前基本上已弃用。目前的建议是RecyclerView改用。但是,对于那些刚接触 Android 编程的人来说,ListView作为了解此类回收适配器的整体设计的开始步骤,仍然是有用的ViewRecyclerView一开始可能有点不知所措。


查看完整回答
反对 回复 2022-01-12
?
MMTTMM

TA贡献1869条经验 获得超4个赞

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


查看完整回答
反对 回复 2022-01-12
  • 2 回答
  • 0 关注
  • 243 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信