Reputation: 172
I have a RecyclverView set up which works perfectly (it may not be the 'best practice' but it works)
The RecyclerView method I implemented was from this video
For this I did the below:
activity_main.xml
layout with
an id @+id/recycler_view
RecyclerViewAdapter
layout_listitem.xml
This worked perfectly and pulls the information from a values
xml called sheep.xml
When you click on one of the items it loads activity GalleryActivity
which presents the information from that item position in a new activity_gallery.xml
layout.
image examples below:
I want to add filtering/search to my RecyclerView. I have followed many guides online from various people and yet still can't get it to work. I created a menu layouts, set up a filterable method and a 'new list' to store the filtered results
Can someone please help me point me in the right direction of a guide I can use with my current set up. I am fairly primitive in my coding knowledge so please be kind.
MainActivity
package com.british.sheep.breeds;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity{
String[ ] url;
String[ ] name;
String[ ] type;
String[ ] established;
String[ ] handle;
String[ ] colour;
String[ ] fleece;
String[ ] staple;
String[ ] micron;
String[ ] gallery;
private static final String TAG = "MainActivity";
//vars
private ArrayList<String> mNames = new ArrayList<>();
private ArrayList<String> mImageUrls = new ArrayList<>();
private ArrayList<String> mTypes = new ArrayList<>();
private ArrayList<String> mEstablisheds = new ArrayList<>();
private ArrayList<String> mHandles = new ArrayList<>();
private ArrayList<String> mColours = new ArrayList<>();
private ArrayList<String> mFleeces = new ArrayList<>();
private ArrayList<String> mStaples = new ArrayList<>();
private ArrayList<String> mMicrons = new ArrayList<>();
private ArrayList<String> mGalleryUrls = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
url = res.getStringArray( R.array.url ) ;
name = res.getStringArray( R.array.name ) ;
type = res.getStringArray( R.array.type ) ;
established = res.getStringArray( R.array.established ) ;
handle = res.getStringArray( R.array.handle ) ;
colour = res.getStringArray( R.array.colour ) ;
fleece = res.getStringArray( R.array.fleece ) ;
staple = res.getStringArray( R.array.staple ) ;
micron = res.getStringArray( R.array.micron ) ;
gallery = res.getStringArray( R.array.gallery ) ;
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
Log.d(TAG, "onCreate: started.");
initImageBitmaps();
}
private void initImageBitmaps(){
Log.d(TAG, "initImageBitmaps: preparing bitmaps.");
for (int i = 0; i < url.length; i++) {
mImageUrls.add(url[i]);
mNames.add(name[i]);
mTypes.add(type[i]);
mEstablisheds.add(established[i]);
mHandles.add(handle[i]);
mColours.add(colour[i]);
mFleeces.add(fleece[i]);
mStaples.add(staple[i]);
mMicrons.add(micron[i]);
mGalleryUrls.add(gallery[i]);
}
initRecyclerView();
}
private void initRecyclerView(){
Log.d(TAG, "initRecyclerView: init recyclerview.");
RecyclerView recyclerView = findViewById(R.id.recycler_view);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, mNames, mImageUrls, mTypes, mEstablisheds, mHandles, mColours, mFleeces, mStaples, mMicrons, mGalleryUrls);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
RecyclerViewAdapter
package com.british.sheep.breeds;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private ArrayList<String> mImageNames = new ArrayList<>();
private ArrayList<String> mImages = new ArrayList<>();
private ArrayList<String> mImageTypes = new ArrayList<>();
private ArrayList<String> mImageEstablisheds = new ArrayList<>();
private ArrayList<String> mImageHandles = new ArrayList<>();
private ArrayList<String> mImageColours = new ArrayList<>();
private ArrayList<String> mImageFleeces = new ArrayList<>();
private ArrayList<String> mImageStaples = new ArrayList<>();
private ArrayList<String> mImageMicrons = new ArrayList<>();
private ArrayList<String> mImageGallerys = new ArrayList<>();
private Context mContext;
public RecyclerViewAdapter(Context context, ArrayList<String> imageNames, ArrayList<String> images, ArrayList<String> types, ArrayList<String> establisheds, ArrayList<String> handles, ArrayList<String> colours, ArrayList<String> fleeces, ArrayList<String> staples, ArrayList<String> microns ,ArrayList<String> gallerys ) {
mImageNames = imageNames;
mImages = images;
mImageTypes = types;
mImageEstablisheds = establisheds;
mImageHandles = handles;
mImageColours = colours;
mImageFleeces = fleeces;
mImageStaples = staples;
mImageMicrons = microns;
mImageGallerys = gallerys;
mContext = context;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Glide.with(mContext)
.asBitmap()
.load(mImages.get(position))
.into(holder.image);
holder.imageName.setText(mImageNames.get(position));
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, GalleryActivity.class);
intent.putExtra("image_url", mImages.get(position));
intent.putExtra("image_name", mImageNames.get(position));
intent.putExtra("image_type", mImageTypes.get(position));
intent.putExtra("image_established", mImageEstablisheds.get(position));
intent.putExtra("image_handle", mImageHandles.get(position));
intent.putExtra("image_colour", mImageColours.get(position));
intent.putExtra("image_fleece", mImageFleeces.get(position));
intent.putExtra("image_staple", mImageStaples.get(position));
intent.putExtra("image_micron", mImageMicrons.get(position));
intent.putExtra("image_gallery", mImageGallerys.get(position));
mContext.startActivity(intent);
}
});
}
@Override
public int getItemCount() {
return mImageNames.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView image;
TextView imageName;
TextView imageType;
TextView imageEstablished;
TextView imageHandle;
TextView imageColour;
TextView imageFleece;
TextView imageStaple;
TextView imageMicron;
ImageView imageGallery;
RelativeLayout parentLayout;
public ViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.image);
imageName = itemView.findViewById(R.id.image_name);
parentLayout = itemView.findViewById(R.id.parent_layout);
imageType = itemView.findViewById(R.id.image_type);
imageEstablished = itemView.findViewById(R.id.image_established);
imageHandle = itemView.findViewById(R.id.image_handle);
imageColour = itemView.findViewById(R.id.image_colour);
imageFleece = itemView.findViewById(R.id.image_fleece);
imageStaple = itemView.findViewById(R.id.image_staple);
imageMicron = itemView.findViewById(R.id.image_micron);
imageGallery = itemView.findViewById(R.id.image_gallery);
}
}
}
GalleryActivity
package com.british.sheep.breeds;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
public class GalleryActivity extends AppCompatActivity {
private static final String TAG = "GalleryActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
overridePendingTransition(R.anim.mtrl_bottom_sheet_slide_in, R.anim.mtrl_bottom_sheet_slide_out);
Log.d(TAG, "onCreate: started.");
getIncomingIntent();
}
@Override
public void onBackPressed() {
finishMyActivity();
}
public void finishMyActivity() {
finish();
overridePendingTransition(R.anim.mtrl_bottom_sheet_slide_in, R.anim.mtrl_bottom_sheet_slide_out);
}
private void getIncomingIntent() {
Log.d(TAG, "getIncomingIntent: checking for incoming intents.");
if (getIntent().hasExtra("image_url") && getIntent().hasExtra("image_name") && getIntent().hasExtra("image_type") && getIntent().hasExtra("image_established") && getIntent().hasExtra("image_handle") && getIntent().hasExtra("image_colour") && getIntent().hasExtra("image_fleece") && getIntent().hasExtra("image_staple") && getIntent().hasExtra("image_micron") && getIntent().hasExtra("image_gallery")) {
Log.d(TAG, "getIncomingIntent: found intent extras.");
String imageUrl = getIntent().getStringExtra("image_url");
String imageName = getIntent().getStringExtra("image_name");
String imageType = getIntent().getStringExtra("image_type");
String imageEstablished = getIntent().getStringExtra("image_established");
String imageHandle = getIntent().getStringExtra("image_handle");
String imageColour = getIntent().getStringExtra("image_colour");
String imageFleece = getIntent().getStringExtra("image_fleece");
String imageStaple = getIntent().getStringExtra("image_staple");
String imageMicron = getIntent().getStringExtra("image_micron");
String imageGallery = getIntent().getStringExtra("image_gallery");
setImage(imageUrl, imageName, imageType, imageEstablished, imageHandle, imageColour, imageFleece, imageStaple, imageMicron, imageGallery);
}
}
private void setImage(String imageUrl, String imageName, String imageType, String imageEstablished, String imageHandle, String imageColour, String imageFleece, String imageStaple, String imageMicron, String imageGallery) {
Log.d(TAG, "setImage: setting te image and name to widgets.");
//TextView name = findViewById(R.id.image_description);
//name.setText(imageName);
setTitle(imageName);
TextView type = findViewById(R.id.image_type);
type.setText(imageType);
TextView established = findViewById(R.id.image_established);
established.setText(imageEstablished);
TextView handle = findViewById(R.id.image_handle);
handle.setText(imageHandle);
TextView colour = findViewById(R.id.image_colour);
colour.setText(imageColour);
TextView fleece = findViewById(R.id.image_fleece);
fleece.setText(imageFleece);
TextView staple = findViewById(R.id.image_staple);
staple.setText(imageStaple);
TextView micron = findViewById(R.id.image_micron);
micron.setText(imageMicron);
ImageView gallery = findViewById(R.id.image_gallery);
Glide.with(this)
.asBitmap()
.load(imageGallery)
.into(gallery);
}
}
Upvotes: 0
Views: 68
Reputation: 632
Here is an example, how you can implement a search filter on your RecyclerView.
I am going to take mImageNames
arrayList on which I'll perform the filter.
There are a couple of things we need to do.
(Make a copy of list, Implement Filterable
to your adapter class, write filter logic and return the filtered value to your MainActivity class)
public class RecyclerViewAdapter extends
RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> implements Filterable {
private ArrayList<String> mImageNames = new ArrayList<>();
private ArrayList<String> copyImageNames ;
public RecyclerViewAdapter (ArrayList<String> imageNames) {
mImageNames = imageNames;
copyImageNames = new ArrayList<>(imageNames);
} }
After your implement Filterable
you need to override this method inside your adapter class.
@Override
public Filter getFilter() { return filter; }
After that we will write the logic to perform filter.I am considering that your mImageNames
list has name of all the sheeps (Balwen,Beltex.....) so that you can filter by their names.
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<String> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(copyImageNames );
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (String s : copyImageNames ) {
if (s.contains(filterPattern)) {
filteredList.add(s);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mImageNames .clear();
mImageNames .addAll((List) results.values);
notifyDataSetChanged();
}
};
Adapter is done , now back to MainActivity Create a menu directory under res folder and save this xml code.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:title="Search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="always|collapseActionView" /></menu>
Now we will inflate the menu and appply the filter to your adapter.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.my_menu, menu);
MenuItem item =menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) item.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
return true;
}
Upvotes: 1
Reputation: 924
First of all create in resources menu for your toolbar:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/menu_item_search"
android:title="@string/search"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom" />
<item
android:id="@+id/menu_setSort"
android:icon="@drawable/ic_sort_off_24dp"
android:title="@string/routes_sort"
app:showAsAction="ifRoom" />
</menu>
add this line to one of items: app:actionViewClass="androidx.appcompat.widget.SearchView"
then in your activity with RecyclerView:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.your_menu, menu);
MenuItem sortIcon = menu.findItem(R.id.menu_setSort);
MenuItem searchItem = menu.findItem(R.id.menu_item_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(this);
return true;
}
Do not forget to implement this interface to your Activivty - implements SearchView.OnQueryTextListener
Because of this interface you implemetnt this methods:
@Override
public boolean onQueryTextSubmit(String query) {
searchResult(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return false;
}
You better make a class instead of all this ArrayLists:
public class OneSheep {
private String mFleeces ;
private String mStaples ;
private String mMicrons ;
private String mGalleryUrls;
private String mNames;
private String mImageUrls ;
private String mTypes;
private String mEstablishedsist;
private String mHandles ;
private String mColours ;
public OneSheep(String names, String imageUrls, String types, String establishedsist, String handles, String colours, String fleeces, String staples, String microns, String galleryUrls) {
mNames = names;
mImageUrls = imageUrls;
mTypes = types;
mEstablishedsist = establishedsist;
mHandles = handles;
mColours = colours;
mFleeces = fleeces;
mStaples = staples;
mMicrons = microns;
mGalleryUrls = galleryUrls;
}
public String getNames() {
return mNames;
}
public String getImageUrls() {
return mImageUrls;
}
public String getTypes() {
return mTypes;
}
public String getEstablishedsist() {
return mEstablishedsist;
}
public String getHandles() {
return mHandles;
}
public String getColours() {
return mColours;
}
public String getFleeces() {
return mFleeces;
}
public String getStaples() {
return mStaples;
}
public String getMicrons() {
return mMicrons;
}
public String getGalleryUrls() {
return mGalleryUrls;
}
}
In your Activity make only one ArrayList<OneSheep> mSheeps
, pass it to your RecaclerView Adapter and this way it is gonna be mach easier to maintain that code. Make your RecyclerView global for MainActivity, call it for example recyclerView and your searchResult()
method will look somethink like that:
private void searchResult(String query) {
ArrayList<OneSheep> newSheepsList = new ArrayList<>();
for (OneSheep sheep:mSheeps) {
if (sheep.getNames().contains(query)){
newSheepsList.add(sheep);
break;
}
if (sheep.getTypes().contains(query)){
newSheepsList.add(sheep);
break;
}
//add any conditions here
}
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, newSheepsList);
recyclerView.setAdapter(adapter);
}
Hope this helps
Upvotes: 0