Hello! I'm trying to release a search in RecyclerView using SearchView . Everything works well, but I need to handle clicking on the filtered list, and I do not know how to implement it.

Code card_view.xml:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:layout_margin="@dimen/card_margin" android:elevation="8dp" card_view:cardCornerRadius="@dimen/card_shop_radius"> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/thumbnail" android:layout_width="match_parent" android:layout_height="@dimen/shop_cover_height" android:background="?attr/selectableItemBackgroundBorderless" android:clickable="true" android:scaleType="fitXY" /> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/thumbnail" android:paddingLeft="@dimen/shop_title_padding" android:paddingRight="@dimen/shop_title_padding" android:paddingTop="@dimen/shop_title_padding" android:textColor="@color/shop_title" android:textSize="@dimen/shop_title" /> <TextView android:id="@+id/distance" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/title" android:paddingBottom="@dimen/distance_padding_bottom" android:paddingLeft="@dimen/shop_title_padding" android:paddingRight="@dimen/shop_title_padding" android:textSize="@dimen/distance" /> </RelativeLayout> </android.support.v7.widget.CardView> </LinearLayout> 

YarObject: model YarObject:

 public class YarObject { private String name; private double distance; private int image; public YarObject() {} public YaroslavlObject(String name, double distance, int image) { this.name = name; this.distance = distance; this.image = image; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getDistance() { return distance; } public void setDistance(double distance) { this.distance = distance; } public int getImage() { return image; } public void setImage(int image) { this.image = image; } } 

RecyclerAdapter code:

 public class RecyclerAdapter extends RecyclerView.Adapter<ShopsAdapter.MyViewHolder> { private Context mContext; private List<YarObject> objectList; public RecyclerAdapter(Context mContext, List<YarObject> objectList) { this.mContext = mContext; this.objectList = objectList; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.shop_card, parent, false); return new MyViewHolder(view); } @Override public void onBindViewHolder(MyViewHolder holder, int position) { YarObject object = objectList.get(position); holder.title.setText(object.getName()); holder.distance.setText(object.getDistance() + " км"); Glide.with(mContext).load(object.getImage()) .into(holder.image); } @Override public int getItemCount() { return objectList.size(); } public class MyViewHolder extends RecyclerView.ViewHolder { TextView title, distance; ImageView image; CardView cardView; public MyViewHolder(View itemView) { super(itemView); title = (TextView) itemView.findViewById(R.id.title); distance = (TextView) itemView.findViewById(R.id.distance); image = (ImageView) itemView.findViewById(R.id.thumbnail); cardView = (CardView) itemView.findViewById(R.id.card_view); } } public void setFilter(List<YarObject> newList) { objectList = new ArrayList<>(); objectList.addAll(newList); notifyDataSetChanged(); } } 

In MainActivity I implemented the SearchView.OnQueryTextListener interface:

 public class MainActivity extends MenuObjectsActivity implements SearchView.OnQueryTextListener { private RecyclerAdapter adapter; private List<YarObject> objectList; @SuppressLint("PrivateResource") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shops); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); if (toolbar != null) { toolbar.setNavigationIcon(R.drawable.abc_ic_ab_back_mtrl_am_alpha); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { onBackPressed(); } }); } initCollapsingToolbar(); RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); objectList = new ArrayList<>(); adapter = new RecyclerAdapter(this, objectList); RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2); if (mRecyclerView != null) { mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true)); mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mRecyclerView.setAdapter(adapter); mRecyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(), mRecyclerView, new RecyclerTouchListener.ClickListener() { @Override public void onClick(View view, int position) { switch (position) { /* case 0: startActivity(new Intent(MainActivity.this, OneActivity.class)); break; case 1: startActivity(new Intent(MainActivity.this, TwoActivity.class)); break; case 2: startActivity(new Intent(MainActivity.this, ThreeActivity.class)); break;*/ } } @Override public void onLongClick(View view, int position) {} })); } prepareObjects(); Glide.with(this) .load(R.drawable.cover_backdrop) .into((ImageView) findViewById(R.id.backdrop)); } @Override protected void prepareObjects() { objectList.add(new YarObject("Bla-bla", 3.9, R.drawable.bla_bla)); objectList.add(new YarObject("Bla-bla-bla", 3.5, R.drawable.bla-bla-bla)); adapter.notifyDataSetChanged(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_object_list, menu); final MenuItem searchItem = menu.findItem(R.id.search_action); SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); searchView.setOnQueryTextListener(this); return true; } @Override public boolean onQueryTextSubmit(String query) { return false; } @Override public boolean onQueryTextChange(String newText) { newText = newText.toLowerCase(); ArrayList<YarObject> filteredList = new ArrayList<>(); for (YarObject object : objectList) { String name = object.getName().toLowerCase(); if (name.contains(newText)) { filteredList.add(object); } } adapter.setFilter(filteredList); return true; } } 

If you handle a click in the onClick() method for RecyclerView , it does not work because there is a fixed position please tell me how you can do it.

  • You need to work not with the position of the element in the list but with the data. Those. in the click listener, you will get an item from the list of displayed data and, depending on its value, do something - YuriySPb
  • I thought and thought over your comment ... Could you please explain in a little more detail? - NikiZ

1 answer 1

@Override public void onQueryInput (String query) {

  if (TextUtils.isEmpty(query)) { refreshAdapter();//это кастомный метод где ты возвращаешь всё на исходные позиции return; } final String quer = lastQuery = query.toLowerCase(); try { mExecutor.execute(new Runnable() { @Override public void run() { final List<Unit> queryUnits = new ArrayList<>(); final Map<Integer, List<Unit>> queryDataModel = new TreeMap<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { if (o1 < o2) return 1; return o2 < o1 ? -1 : 0; } }); for (Unit unit : mAllUnits //Это лист со всеми элементами, которые есть ) { if (StringScore.score(unit.getLocationTag(), quer) > 0.1 || StringScore.score(unit.getCameraName(), quer) > 0.1 || StringScore.score(unit.getLocaleMediaDate(), quer) > 0.1) queryUnits.add(unit); } for (Unit unit : queryUnits ) { Integer key = unit.getSimpleIntegerKey(); if (queryDataModel.containsKey(key)) { queryDataModel.get(key).add(unit); } else { queryDataModel.put(key, new ArrayList<Unit>()); queryDataModel.get(key).add(unit); } } for (Map.Entry<Integer, List<Unit>> entry : queryDataModel.entrySet() ) { Collections.sort(entry.getValue(), Unit.UNIT_COMPARATOR); } Collections.sort(queryUnits, Unit.UNIT_COMPARATOR); new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (lastQuery.equals(quer)) { mDataModel = queryDataModel; mUnits = queryUnits; //Это лист, количество элементов котороe указано в getItemCount(); notifyDataSetChanged();//благодаря этому методу всё обновится } } }); } }); } catch (RejectedExecutionException e) { Log.e(getClass().getSimpleName(), e.getMessage()); } } 
  • Where should I redefine this method? - NikiZ
  • Where the request comes from searchView, I don’t know how you have the architecture, but the query in the signature is what is entered into the searchView, onQueryInputListener, or something similar, the code that it threw off inside the adapter. - AZ