简体   繁体   English

使用 RecyclerView 的 SearchView 过滤器

[英]SearchView filter with RecyclerView

I have tried to implement a SearchView with suggestions (filter) in Fragment, but I have not managed it.我试图在 Fragment 中实现带有建议(过滤器)的 SearchView,但我没有成功。 I tried almost every tutorial but nothing worked for me.我几乎尝试了所有教程,但对我没有任何帮助。 I would appreciate any help.我将不胜感激任何帮助。 Thank you谢谢

XML... 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" />

Fragment分段

@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;

Adapter适配器

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);
        }

    }

}

You can create class which extends 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();
    }

} }

And then you can add this Filter to yours ContactsAdapter .然后您可以将此过滤器添加到您的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);
    }

}

} }

searchview 过滤器值得 recyclerview

In your adapter class implement filterable and overide it's method.在您的适配器类中实现可过滤并覆盖它的方法。

    @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;
}

in your main activity create searchview and listen to onQueryTextChange.在您的主要活动中创建搜索视图并收听 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;
}

full tutorial and source code.完整的教程和源代码。 Recyclerview with search / filter带有搜索/过滤器的 Recyclerview

Try This试试这个

@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;
        }
    });
}

implement Filterable to your Adapter class实现 Filterable 到您的 Adapter 类

public class CategoryAdapter extends RecyclerView.Adapter implements 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);
}

} }

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);
}

I know it might be late, but maybe it can help someone.我知道它可能会迟到,但也许它可以帮助某人。 If you're trying to search without providing a custom filter, do so with the adapter's getFilter override.如果您尝试在不提供自定义过滤器的情况下进行搜索,请使用适配器的 getFilter 覆盖来执行此操作。 But if your search uses custom logic options, do it in setQueryTextListener in the onQueryTextChange section.但是,如果您的搜索使用自定义逻辑选项,请在 onQueryTextChange 部分的 setQueryTextListener 中进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM