【问题标题】:SearchView filter with RecyclerView带有 RecyclerView 的 SearchView 过滤器
【发布时间】:2016-06-29 11:35:12
【问题描述】:

我尝试在 Fragment 中实现带有建议(过滤器)的 SearchView,但我没有管理它。我几乎尝试了所有教程,但对我没有任何帮助。我将不胜感激任何帮助。谢谢

XML ...

    <!--appBar layout-->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">

        <!--searchView layout-->
        <android.support.v7.widget.SearchView
            android:id="@+id/search_view"
            app:layout_scrollFlags="scroll|enterAlways"
            android:iconifiedByDefault="false"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:closeIcon="@drawable/ic_clear_white_18dp"
            app:searchIcon="@drawable/ic_search_white_24dp"
            app:queryHint="@string/search_contact"
            app:iconifiedByDefault="false"
            android:background="@color/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

       </android.support.design.widget.AppBarLayout>

        <!-- recycler view-->
        <android.support.v7.widget.RecyclerView
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

片段

@Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_contact_list, container, false);

        searchView = (SearchView)view.findViewById(R.id.search_view);
        fabButton = (FloatingActionButton)view.findViewById(R.id.fab_button);

        //recycler view
        recyclerView = (RecyclerView)view.findViewById(R.id.recycler_view);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        contacts = SugarRecord.listAll(Contact.class);
        contactsAdapter = new ContactsAdapter(getActivity(), contacts);
        recyclerView.setAdapter(contactsAdapter);

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

            @Override
            public boolean onQueryTextChange(String newText) {
                // TODO: setFilter

                return true;
            }
        });

        return view;

适配器

public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactVH> {

    List<Contact> mContact;
    List<Contact> mContactFilter;

    Context mContext;

    public ContactsAdapter(Context context, List<Contact> contact) {
        this.mContact = contact;
        this.mContext = context;
    }

    @Override
    public ContactVH onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item_contact, parent, false);
        ContactVH viewHolder = new ContactVH(view);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ContactVH holder, int position) {
        holder.name.setText(mContact.get(position).getName());
    }

    @Override
    public int getItemCount() {
        return mContact.size();
    }

    class ContactVH extends RecyclerView.ViewHolder {
        @BindView(R.id.contact_name)
        TextView name;

        public ContactVH(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }

    }

}

【问题讨论】:

标签: android adapter searchview android-recyclerview


【解决方案1】:

您可以创建扩展 Filter

的类
class YourFilterClass extends Filter {

private List<Contact> contactList;
private List<Contact> filteredContactList;
private ContactsAdapter adapter;

    public YourFilterClass(List<Contact> contactList, ContactsAdapter adapter) {
     this.adapter = adapter;
     this.contactList = contactList;
     this.filteredContactList = new ArrayList();
    }

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
    filteredContactList.clear();
    final FilterResults results = new FilterResults();

    //here you need to add proper items do filteredContactList
     for (final Contact item : contactList) {
            if (item.getName().toLowerCase().trim().contains("pattern")) { 
                filteredContactList.add(item);
            }
        }

        results.values = filteredContactList;
        results.count = filteredContactList.size();
        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        adapter.setList(filteredContactList);
        adapter.notifyDataSetChanged();
    }

}

然后您可以将此 Filter 添加到您的 ContactsAdapter

public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ContactVH> {

List<Contact> mContact;
List<Contact> mContactFilter;
YourFilterClass filter;

Context mContext;

public ContactsAdapter(Context context, List<Contact> contact) {
    this.mContact = contact;
    this.mContactFilter = contact;
    this.mContext = context;
    filter = new YourFilterClass(mContact, this);
}

@Override
public ContactVH onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item_contact, parent, false);
    ContactVH viewHolder = new ContactVH(view);
    return viewHolder;
}

@Override
public void onBindViewHolder(ContactVH holder, int position) {
    holder.name.setText(mContactFilter.get(position).getName());
}
// set adapter filtered list
public void setList(List<Contact> list) {
    this.mContactFilter = list;
}
//call when you want to filter
public void filterList(String text) {
    filter.filter(text);
}

@Override
public int getItemCount() {
    return mContactFilter.size();
}

class ContactVH extends RecyclerView.ViewHolder {
    @BindView(R.id.contact_name)
    TextView name;

    public ContactVH(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }

}

}

【讨论】:

  • 非常感谢!所以我必须在 OnQueryTextListener() 上调用 filterList ?
  • 是的,你可以在 onQueryTextChange() 中调用它
  • 好的,现在不行了,我看看。还有一个问题。这到底是做什么的: for (final Contact item : contactList) { if (item.getName().toLowerCase().trim().contains("pattern")) { filteredContactList.add(item); } } 我的意思是 ....contains("this word here")
  • 在这里您应该将您想要的所有项目添加到您的过滤列表中。这只是一个例子。如果“这里的这个词”将是项目名称的一部分,那么这个表达将是正确的
  • 那我怎么知道有来自SearchView的信件呢?例如,如果我写“a”,它将显示所有以“a..”开头的名称
【解决方案2】:

在您的适配器类中实现可过滤并覆盖它的方法。

    @Override
public Filter getFilter() {

    Filter filter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) {
            FilterResults filterResults = new FilterResults();

            if(charSequence == null | charSequence.length() == 0){
                filterResults.count = getUserModelListFiltered.size();
                filterResults.values = getUserModelListFiltered;

            }else{
                String searchChr = charSequence.toString().toLowerCase();

                List<UserModel> resultData = new ArrayList<>();

                for(UserModel userModel: getUserModelListFiltered){
                    if(userModel.getUserName().toLowerCase().contains(searchChr)){
                        resultData.add(userModel);
                    }
                }
                filterResults.count = resultData.size();
                filterResults.values = resultData;

            }

            return filterResults;
        }

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) {

            userModelList = (List<UserModel>) filterResults.values;
            notifyDataSetChanged();

        }
    };
    return filter;
}

在您的主要活动中创建搜索视图并收听 onQueryTextChange。

 @Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);

    MenuItem menuItem = menu.findItem(R.id.search_view);

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

    searchView.setMaxWidth(Integer.MAX_VALUE);

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

        @Override
        public boolean onQueryTextChange(String newText) {

            usersAdapter.getFilter().filter(newText);
            return true;
        }
    });



    return  true;
}

完整的教程和源代码。 Recyclerview with search / filter

【讨论】:

    【解决方案3】:

    试试这个

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    
        inflater.inflate(R.menu.main_menu, menu);
    
        MenuItem mSearchMenuItem = menu.findItem(R.id.search);
        SearchView searchView = (SearchView) mSearchMenuItem.getActionView();
    
        search(searchView);
    }
    
    public static void search(android.support.v7.widget.SearchView searchView) {
    
        searchView.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
    
                return false;
            }
    
            @Override
            public boolean onQueryTextChange(String newText) {
                mCategoryAdapter.getFilter().filter(newText);
                return true;
            }
        });
    }
    

    为您的 Adapter 类实现 Filterable

    公共类 CategoryAdapter 扩展 RecyclerView.Adapter 实现 Filterable {

    private List<Category> categoryList;
    private List<Category> mFilteredList;
    
    
    public CategoryAdapter(List<Category> categoryList) {
    
        this.categoryList = categoryList;
        this.mFilteredList = categoryList;
    }
    
    @Override
    public CategoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.category_card, parent, false);
    
        return new CategoryViewHolder(itemView);
    }
    
    @Override
    public void onBindViewHolder(CategoryViewHolder holder, int position) {
            Category category = mFilteredList.get(position);
            holder.catname.setText(category.getCatName());
            holder.items.setText(category.getCatItems()+" Items");
    
    
    }
    
    @Override
    public int getItemCount() {
        return mFilteredList.size();
    }
    
    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
    
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
    
                    mFilteredList = categoryList;
                } else {
    
                    List<Category> filteredList = new ArrayList<>();
    
                    for (Category category : categoryList) {
    
                        if (category.getCatName().toLowerCase().contains(charString) || String.valueOf(category.getId()).contains(charString)) {
    
                            filteredList.add(category);
                        }
                    }
    
                    mFilteredList = filteredList;
                }
    
                FilterResults filterResults = new FilterResults();
                filterResults.values = mFilteredList;
                return filterResults;
            }
    
            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                mFilteredList = (List<Category>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }
    
    public class CategoryViewHolder extends RecyclerView.ViewHolder {
        public TextView catname, items;
        public ImageView imgView;
    
        public CategoryViewHolder(View view) {
            super(view);
            catname = view.findViewById(R.id.categorycard_cate_name);
            items = view.findViewById(R.id.categorycard_lbl_cat_items);
    
        }
    }
    
    public void removeItem(int position) {
        mFilteredList.remove(position);
        // notify the item removed by position
        // to perform recycler view delete animations
        // NOTE: don't call notifyDataSetChanged()
        notifyItemRemoved(position);
    }
    
    public void restoreItem(Category category, int position) {
        mFilteredList.add(position, category);
        // notify item added by position
        notifyItemInserted(position);
    }
    

    }

    【讨论】:

      【解决方案4】:
      SearchView addCustomerPageSearchView = findViewById(R.id.addCustomerPageSearchView);
          addCustomerPageSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
              @Override
              public boolean onQueryTextSubmit(String query) {
      
                  searchResult(query);
      
                  return true;
              }
      
              @Override
              public boolean onQueryTextChange(String newText) {
      
                  searchResult(newText);
      
                  return true;
              }
          });
      
      
          private void searchResult(String query)
          {
          String q = query.toLowerCase();
          List<ModelContacts> updatedList = new ArrayList<>();
      
          for (ModelContacts modelContacts : contactList)
          {
              if(modelContacts.getName().toLowerCase().contains(q))
              {
                  updatedList.add(modelContacts);
              }
          }
      
          adapter = new ContactAdapter(getApplicationContext(), updatedList);
          contactListRecycler.setAdapter(adapter);
      }
      

      【讨论】:

        【解决方案5】:

        我知道它可能会迟到,但也许它可以帮助某人。如果您尝试在不提供自定义过滤器的情况下进行搜索,请使用适配器的 getFilter 覆盖。但如果您的搜索使用自定义逻辑选项,请在 onQueryTextChange 部分的 setQueryTextListener 中进行。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-03
          • 1970-01-01
          • 1970-01-01
          • 2016-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-07
          相关资源
          最近更新 更多