RecyclerView 的 SearchView 不起作用

Posted

技术标签:

【中文标题】RecyclerView 的 SearchView 不起作用【英文标题】:SearchView for RecyclerView not working 【发布时间】:2018-10-19 05:34:55 【问题描述】:

我已经为片段中的 recyclerview 实现了 searchview 过滤器,如下所示,但是当我在 searchview 中输入查询时没有任何反应。

我的片段类:DiscussionForum.java

public class DiscussionForum extends Fragment implements ForumAdapter.ForumAdapterListener 


private TextView socname;
private EditText messageinput;
private SearchView search;
// SearchView searchView;
private FloatingActionButton messagesend;
ProgressDialog progressDialog;
private static final String TAG = "Discussion Forum";
private RecyclerView recyclerView;
private List<ForumData> forumlist;
private ForumAdapter mAdapter;
private OnFragmentInteractionListener mListener;
private LinearLayout list;
private String sendurl, geturl;

public DiscussionForum() 
    // Required empty public constructor



public static DiscussionForum newInstance(String param1, String param2) 
    DiscussionForum fragment = new DiscussionForum();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;


@Override

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState)       
    View view = inflater.inflate(R.layout.fragment_discussion_forum, container, false);
    onButtonPressed("Discussion Forum");      
    forumlist = new ArrayList<>();
    recyclerView = view.findViewById(R.id.listviewforum);
    list = view.findViewById(R.id.list);
    search = view.findViewById(R.id.search);
    int resId = R.anim.layout_animation_fall_down;
    LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(getContext(), resId);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(mLayoutManager);
    recyclerView.setLayoutAnimation(animation);
    mAdapter = new ForumAdapter(getContext(), forumlist, this);
    progressDialog = new ProgressDialog(getContext());
    progressDialog.setCancelable(false);        
    geturl = "";         
    fetchforumdata(getActivity().getIntent().getStringExtra("id"));
    search.setOnQueryTextListener(new SearchView.OnQueryTextListener() 
        @Override
        public boolean onQueryTextSubmit(String query) 
            return false;
        

        @Override
        public boolean onQueryTextChange(String newText) 
            mAdapter.getFilter().filter(newText);
            return true;
        
    );

    return view;




private void fetchforumdata(final String id1) 
    progressDialog.setMessage("Loading...");
    showDialog();
    StringRequest request = new StringRequest(Request.Method.GET,
            geturl + id1,
            new Response.Listener<String>() 
                @Override
                public void onResponse(String response) 
                    // Log.d("tag2","id"+id1);
                    Log.d(TAG, "Response Prop: " + response.toString());
                    hideDialog();
                    try 
                        JSONObject jObj = new JSONObject(response);
                        boolean error = jObj.getBoolean("errors");
                        if (!error) 
                            JSONObject dataobj = jObj.getJSONObject("data");
                            JSONArray ticketarray = dataobj.getJSONArray("result");
                            if (ticketarray.length() == 0) 
                                list.setVisibility(View.VISIBLE);
                             else 
                                recyclerView.setVisibility(View.VISIBLE);
                                List<ForumData> items = new Gson().fromJson(ticketarray.toString(), new TypeToken<List<ForumData>>() 
                                .getType());

                                forumlist.clear();
                                forumlist.addAll(items);
                                recyclerView.setAdapter(mAdapter);
                            
                         else 
                            // String errorMsg = jObj.getString("error_msg");
                            Toast.makeText(getContext(),
                                    "Try again or report an issue", Toast.LENGTH_LONG).show();
                        
                     catch (JSONException e) 
                        e.printStackTrace();
                    

                
            , new Response.ErrorListener() 
        @Override
        public void onErrorResponse(VolleyError error) 
            // error in getting json
            Log.e(TAG, "Error: " + error.getMessage());
            Toast.makeText(getContext(), "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
            hideDialog();
        
    );

    MyApplication.getInstance().addToRequestQueue(request);



// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(String title) 
    if (mListener != null) 
        mListener.onFragmentInteraction(title);
    


@Override
public void onAttach(Context context) 
    super.onAttach(context);
    if (context instanceof OnFragmentInteractionListener) 
        mListener = (OnFragmentInteractionListener) context;
     else 
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
    


@Override
public void onDetach() 
    super.onDetach();
    mListener = null;


private void showDialog() 
    if (!progressDialog.isShowing())
        progressDialog.show();


private void hideDialog() 
    if (progressDialog.isShowing())
        progressDialog.dismiss();


@Override
public void onDocumentSelected(String id) 



public interface OnFragmentInteractionListener 
    // TODO: Update argument type and name
    void onFragmentInteraction(String title);

我的适配器类:ForumAdapter

public class ForumAdapter extends RecyclerView.Adapter<ForumAdapter.MyViewHolder> implements Filterable 
private Context context;
private List<ForumData> ticketlist;
private List<ForumData> filterlist;
private ForumAdapterListener listener;




public class MyViewHolder extends RecyclerView.ViewHolder 
    TextView username,createdat,forummessage,flatno,category,likes,subcount;
    ImageView edit;

    public MyViewHolder(View view) 
        super(view);
        username=view.findViewById(R.id.user_name2);
        createdat=view.findViewById(R.id.date2);
        edit = view.findViewById(R.id.profile_icon2);
        forummessage=view.findViewById(R.id.forum_message);
        flatno=view.findViewById(R.id.flat_no);
        category=view.findViewById(R.id.category);
        likes=view.findViewById(R.id.likes_data);
        subcount=view.findViewById(R.id.count_data);

    

public ForumAdapter(Context context, List<ForumData> ticketlist, ForumAdapterListener listener) 
    this.context = context;
    this.listener = listener;
    this.ticketlist = ticketlist;
    this.filterlist=ticketlist;


@Override
public ForumAdapter.MyViewHolder onCreateViewHolder( ViewGroup parent, int viewType) 
    View itemView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.discussion_forum_item, parent, false);

    return new MyViewHolder(itemView);


@Override
public void onBindViewHolder( ForumAdapter.MyViewHolder holder, int position) 
    final ForumData contact = ticketlist.get(position);
    holder.username.setText(contact.getUsername());
    holder.flatno.setText(contact.getFlattitle());
    holder.forummessage.setText(contact.getMessage());
    holder.createdat.setText(contact.getCreated_at());
    holder.category.setText(contact.getCategory());      
    holder.likes.setText(contact.getLikes());       
    holder.subcount.setText(contact.getSubcount());
    Glide.with(context)
            .load(url+".jpg")
            .apply(new RequestOptions().circleCrop().placeholder(R.drawable.man).error(R.drawable.man))
            .into(holder.edit);

        
    );



@Override
public int getItemCount() 
    return ticketlist.size();



@Override
public Filter getFilter() 
    return new Filter() 
        @Override
        protected FilterResults performFiltering(CharSequence charSequence) 
            String charString = charSequence.toString();
            if (charString.isEmpty()) 
                filterlist = ticketlist;
             else 
                List<ForumData> filteredList = new ArrayList<>();
                for (ForumData row : ticketlist) 

                    // name match condition. this might differ depending on your requirement
                    // here we are looking for name or phone number match
                    if (row.getUsername().toLowerCase().contains(charString.toLowerCase()) || row.getCategory().contains(charSequence)) 
                        filteredList.add(row);
                    
                

                filterlist = filteredList;
            

            FilterResults filterResults = new FilterResults();
            filterResults.values = filterlist;
            return filterResults;
        

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) 
            filterlist = (ArrayList<ForumData>) results.values;
            notifyDataSetChanged();

        
    
     ;

public interface ForumAdapterListener 
    void onDocumentSelected(String contact);

我经历过很多解决方案,例如 here , here ,here 但我无法弄清楚我的代码有什么问题。请帮我找出确切的问题出在哪里。

【问题讨论】:

【参考方案1】:

您的适配器实现存在多个问题。如果我正确理解您的代码,您希望保留对未过滤项目列表 (List&lt;ForumData&gt; ticketlist) 的引用并过滤此列表并在屏幕上显示过滤结果 (List&lt;ForumData&gt; filterlist)。

首先,您想在屏幕上显示filterlist,因此在onBindViewHolder()getItemCount() 中您需要使用filterlist 而不是ticketlist

其次,您要确保ticketlist 保持不变,以便以后的所有搜索都针对相同的内容。为此,您必须将所有filterlist = ticketlist; 替换为filterlist = new ArrayList&lt;&gt;(ticketlist);(在您的构造函数和performFiltering() 中)以避免更改ticketlist 的内容。

这至少应该使您的代码正常运行。我建议您观看this 视频,了解 Java 以及对象和引用。

【讨论】:

【参考方案2】:

另一种方法是过滤数据并刷新onQueryTextChange中的recyclerview适配器:

searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() 
    @Override
    public boolean onQueryTextSubmit(String query) 


    

    @Override
    public boolean onQueryTextChange(String newText) 
         ArrayList< ForumData > filteredData = new ArrayList<>();

        for (ForumData forumData : data) 
            if (forumData..getUsername().toLowerCase().contains(newText.toLowerCase())) 

                filteredData.add(forumData);

            

        

        adapter = new ForumAdapter(data, getContext() , this);
        recyclerView.setAdapter(adapter);
        return true ;

    
)

【讨论】:

adapter = new ContactsAdapter(this, contactList, this);当我尝试添加此行时,它会生成有关侦听器参数(第三个参数)作为意外参数的错误。如何解决? 试试adapter = new ContactsAdapter(this, contactList, DiscussionForum.this); 好的,我把它改成了 adapter = new ContactsAdapter(this, contactList, DiscussionForum.this);及其现在的工作

以上是关于RecyclerView 的 SearchView 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

如何在基于 SQLite 的 recyclerview 中实现 searchview? - 安卓

为啥 recyclerview 的 searchview 不起作用?

使用Recyclerview的searchview EditText

当我们在 recyclerview 中使用 searchview 时,我们如何将搜索到的字符着色?

使用 Room 和 RecyclerView 在 SearchView 中添加过滤器

SearchView 在回收站视图中不起作用