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<ForumData> ticketlist
) 的引用并过滤此列表并在屏幕上显示过滤结果 (List<ForumData> filterlist
)。
首先,您想在屏幕上显示filterlist
,因此在onBindViewHolder()
和getItemCount()
中您需要使用filterlist
而不是ticketlist
。
其次,您要确保ticketlist
保持不变,以便以后的所有搜索都针对相同的内容。为此,您必须将所有filterlist = ticketlist;
替换为filterlist = new ArrayList<>(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 时,我们如何将搜索到的字符着色?