I'm having trouble updating a RecyclerView with SearchView results in a Fragment.
Doing the actual search seems to work fine as I've stepped through the code at "performFiltering" and the "publishResults" has the correct list. But I can't seem to figure out how to update the RecyclerView. I've been staring at this code for 3 days now and is likely a simple solution I'm overlooking.
MyMoviesFragment
public class MyMoviesFragment extends Fragment {
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
private static final boolean DEFAULT_SORT_ORDER_IS_ASC = false;
private static final int MY_MOVIES_LOADER_ID = 173201;
private ArrayList<Movie> _movies = new ArrayList();
private ArrayList<Movie> _moviesRaw = new ArrayList();
private Button _btnMoviesNotFound;
private DBHandler _repository;
private MyMoviesAdapter _myMoviesAdapter;
private ProgressBar _progressBar;
private RecyclerView _rvMovies;
private SharedPreferences _preferences;
private View _view;
public MyMoviesFragment() {
// Required empty public constructor
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// inflater.inflate(R.menu.main, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
_myMoviesAdapter.getFilter().filter(newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
this._view = inflater.inflate(R.layout.fragment_my_movies, container, DEFAULT_SORT_ORDER_IS_ASC);
getActivity().setTitle(R.string.movies_fragment_title);
this._repository = DBHandler.getInstance(getActivity());
this._progressBar = (ProgressBar) this._view.findViewById(R.id.progressBar2);
this._progressBar.setVisibility(View.VISIBLE);
this._rvMovies = (RecyclerView) this._view.findViewById(R.id.rvMovies);
this._rvMovies.setLayoutManager(new LinearLayoutManager(getActivity()));
this._myMoviesAdapter = new MyMoviesAdapter(this._movies, this);
this._rvMovies.setAdapter(this._myMoviesAdapter);
this._btnMoviesNotFound = (Button) this._view.findViewById(R.id.btnMoviesNotFound);
if (savedInstanceState == null) {
loadMyMoviesList();
}
return this._view;
}
public void loadMyMoviesList() {
getLoaderManager().initLoader(MY_MOVIES_LOADER_ID, null, new LoaderManager.LoaderCallbacks<ArrayList<Movie>>() {
#NonNull
#Override
public Loader<ArrayList<Movie>> onCreateLoader(int id, Bundle args) {
return new MyMoviesLoader(MyMoviesFragment.this.getContext());
}
public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> movies) {
if (movies != null) {
MyMoviesFragment.this._movies.clear();
Iterator it = movies.iterator();
while (it.hasNext()) {
MyMoviesFragment.this._movies.add((Movie) it.next());
}
MyMoviesFragment.this._moviesRaw = new ArrayList(MyMoviesFragment.this._movies);
MyMoviesFragment.this._myMoviesAdapter.notifyDataSetChanged();
MyMoviesFragment.this.displayListState();
}
}
public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
}
}).forceLoad();
}
public void displayListState() {
this._progressBar.setVisibility(View.GONE);
if (this._movies.size() < 1) {
this._rvMovies.setVisibility(View.GONE);
this._btnMoviesNotFound.setVisibility(View.VISIBLE);
return;
}
this._btnMoviesNotFound.setVisibility(View.GONE);
this._rvMovies.setVisibility(View.VISIBLE);
}
}
MyMoviesAdapter
public class MyMoviesAdapter extends RecyclerView.Adapter<MyMoviesAdapter.ViewHolder> implements Filterable {
private Activity _activity;
private ArrayList<Movie> _movieListFull;
private ArrayList<Movie> _movieListFiltered;
private DBHandler _repository = DBHandler.getInstance(this._activity);
private Fragment _fragment;
public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) {
this._activity = fragment.getActivity();
this._fragment = fragment;
this._movieListFull = movies;
}
protected class ViewHolder extends RecyclerView.ViewHolder {
private CardView cardMovie;
private TextView lblMovieTitle;
public ViewHolder(View itemView) {
super(itemView);
this.cardMovie = (CardView) itemView.findViewById(R.id.cardMovie);
this.lblMovieTitle = (TextView) itemView.findViewById(R.id.lblMovieTitle);
}
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_movie, parent, false));
}
// Replace the contents of a view (invoked by the layout manager)
// Binds the data to the Views in each row
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// Get the data model based on position
Movie movie = _movieListFull.get(position);
viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle()));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this._movieListFull.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
_movieListFiltered = _movieListFull;
} else {
ArrayList<Movie> filteredList = new ArrayList<>();
for (Movie movie : _movieListFull) {
if (movie.getTitle().toLowerCase().contains(charString)) {
filteredList.add(movie);
}
}
_movieListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = _movieListFiltered;
filterResults.count = _movieListFiltered.size();
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
_movieListFiltered = (ArrayList<Movie>) filterResults.values;
notifyDataSetChanged();
}
};
}
}
If _movieListFull is full data set, then _movieListFiltered should be used for display. Therefore getItemCount() and onBindViewHolder() should refer to _movieListFiltered.
Try the following changes:
public MyMoviesAdapter(ArrayList<Movie> movies, Fragment fragment) {
this._activity = fragment.getActivity();
this._fragment = fragment;
this._movieListFiltered = movies;
_movieListFull = new ArrayList<>();
_movieListFull.addAll(movies);
}
// Replace the contents of a view (invoked by the layout manager)
// Binds the data to the Views in each row
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
// Get the data model based on position
Movie movie = _movieListFiltered.get(position);
viewHolder.lblMovieTitle.setText(String.valueOf(movie.getTitle()));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this._movieListFiltered.size();
}
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
//_movieListFiltered = _movieListFull;
_movieListFiltered.addAll(_movieListFull);
} else {
ArrayList<Movie> filteredList = new ArrayList<>();
for (Movie movie : _movieListFull) {
if (movie.getTitle().toLowerCase().contains(charString)) {
filteredList.add(movie);
}
}
_movieListFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = _movieListFiltered;
filterResults.count = _movieListFiltered.size();
return filterResults;
}
Hope that helps!
Related
I am creating an app I using search view in fragment to search recycler view ArrayList data but below method not showing the result
Not show my filter result in recycler view
How to show filter result in recycle view in the fragment.
anyone tell me what changes below code to fix this problem
please help me
Fragment
import in.getagf.pickuplines.Model.dataAdapter;
import in.getagf.pickuplines.Model.dataItem;
/**
* A simple {#link Fragment} subclass.
*/
public class LatestFragment extends Fragment {
private View myView;
private DatabaseReference RootRef, AdsRef;
private AdView adView;
private RecyclerView mRecyclerView;
dataAdapter mDataAdapter;
private RecyclerView.LayoutManager mDataLayoutManager;
public LatestFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
myView = inflater.inflate(R.layout.fragment_latest, container, false);
RootRef = FirebaseDatabase.getInstance().getReference().child("App_Data");
AdsRef = FirebaseDatabase.getInstance().getReference().child("Apps Link").child("AdsUnitID");
mRecyclerView = (RecyclerView) myView.findViewById(R.id.latest_recyclerView);
mDataLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mDataLayoutManager);
mDataAdapter = new dataAdapter(getDataSetLines(), getActivity());
mRecyclerView.setAdapter(mDataAdapter);
getResult.clear();
// offlinedata();
receiverData();
return myView;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.home, menu);
MenuItem item = menu.findItem(R.id.action_search);
SearchView sv = (SearchView) MenuItemCompat.getActionView(item);
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
return false;
}
#Override
public boolean onQueryTextChange(String newtext) {
mDataAdapter.getFilter().filter(newtext);
return false;
}
});
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle item selection
switch (item.getItemId()) {
case R.id.action_search:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void receiverData()
{
RootRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if (dataSnapshot.exists() && !dataSnapshot.child("category").getValue().toString().equals("Good Night"))
{
String Lines = dataSnapshot.child("lines").getValue().toString();
String Pic = dataSnapshot.child("pic").getValue().toString();
String visite_id = dataSnapshot.getKey();
dataItem obj = new dataItem(visite_id, Lines, Pic);
getResult.add(obj);
mDataAdapter.notifyDataSetChanged();
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
AdsRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String fB_Latest = dataSnapshot.child("fB_Latest").getValue(String.class);
// Facebook Banner Ads
adView = new AdView(getActivity(), fB_Latest, AdSize.BANNER_HEIGHT_50);
LinearLayout adContainer = (LinearLayout) myView.findViewById(R.id.latest_facebook_ads);
adContainer.addView(adView);
adView.loadAd();
// end
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
#Override
public void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
private ArrayList<dataItem> getResult = new ArrayList<dataItem>();
private List<dataItem> getDataSetLines() {
return getResult;
}
}
dataAdapter
/**
* Created by Vinay Singh on 16/02/2019.
*/
public class dataAdapter extends RecyclerView.Adapter<DataViewHolders>
implements Filterable {
private List<dataItem> myList;
private List<dataItem> myListFull;
private Context context;
public dataAdapter(List<dataItem> myList, Context context) {
this.myList = myList;
this.context = context;
myListFull = new ArrayList<>(myList);
}
#Override
public DataViewHolders onCreateViewHolder(ViewGroup viewGroup, int position) {
View layoutView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_view, null, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutView.setLayoutParams(lp);
DataViewHolders rcv = new DataViewHolders(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(DataViewHolders holder, int position) {
String lines = myList.get(position).getLines();
holder.mLines.setText(myList.get(position).getLines());
holder.mVisit_id.setText(myList.get(position).getVisite_id());
if (myList.get(position).getPic().equals("default")) {
Picasso.get().load(R.drawable.app_logo).into(holder.mImage);
}else if (myList.get(position).getPic().equals("Funny"))
{
Picasso.get().load(R.drawable.funny).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Romantic"))
{
Picasso.get().load(R.drawable.romantic).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Chat Tips"))
{
Picasso.get().load(R.drawable.chat).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Good Morning"))
{
Picasso.get().load(R.drawable.goodmorning).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Motivation"))
{
Picasso.get().load(R.drawable.motivation).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Shayri"))
{
Picasso.get().load(R.drawable.shayari).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("WhatsApp"))
{
Picasso.get().load(R.drawable.whatsapp).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Jokes"))
{
Picasso.get().load(R.drawable.jokes).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Good Night"))
{
Picasso.get().load(R.drawable.goodnight).into(holder.mImage);
}
else if (myList.get(position).getPic().equals("Chatting"))
{
Picasso.get().load(R.drawable.chatting).into(holder.mImage);
}
else
{
Picasso.get().load(R.drawable.app_logo).into(holder.mImage);
}
}
#Override
public int getItemCount() {
return this.myList.size();
}
#Override
public Filter getFilter() {
return myListFilter;
}
private Filter myListFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String charString = constraint.toString();
if (charString.isEmpty())
{
myListFull = myList;
}
else
{
List<dataItem> filteredList = new ArrayList<>();
for (dataItem item : myListFull)
{
if (item.getLines().contains(charString)){
filteredList.add(item);
}
}
myListFull = filteredList;
}
FilterResults results = new FilterResults();
results.values = myListFull;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
myList.clear();
myList.addAll((List) results.values);
notifyDataSetChanged();
}
};
}
List<dataItem> filteredList = new ArrayList<>();
for (dataItem item : myList) // myListFull wrong
{
if (item.getLines().contains(charString)){
filteredList.add(item);
}
}
myListFull = filteredList;
First Remove this code in your fragment
private ArrayList<dataItem> getResult = new ArrayList<dataItem>();
private List<dataItem> getDataSetLines() {
return getResult;
}
}
and intialized ArrayList in above of onCreateView method and change this code in onCreateView method
mDataAdapter = new dataAdapter(getResult, getContext());
Now add this code in your Adapter
List<dataItem> filteredList = new ArrayList<>();
for (dataItem item : myList) // myListFull wrong
{
if (item.getLines().contains(charString)){
filteredList.add(item);
}
}
myListFull = filteredList;
In your myListFull ArrayList to not add data of myList.
I hope this can help You!
Thank You.
hi all I have implemented SearchView inside RecyclerView but when I search character name it is not searching any name and I have followed this tutorial
below my adapter class where I have implemented recyclerview with
Filtarable
public class LeovegasAdapter extends RecyclerView.Adapter implements Filterable {
private List<Hero> heros;
private List<Hero> filtarableList;
public LeovegasAdapter(List<Hero> heros) {
this.heros = heros;
filtarableList = filtarableList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.hero_list, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
Hero hero = heros.get(position);
holder.heroId.setText(hero.getId());
holder.heroName.setText(hero.getName());
}
#Override
public int getItemCount() {
return heros.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
filtarableList = heros;
} else {
ArrayList<Hero> filteredList = new ArrayList<>();
for (Hero hero : heros) {
if (hero.getId().toLowerCase().contains(charString) || hero.getName().toLowerCase().contains(charString)) {
filteredList.add(hero);
}
}
filtarableList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = filtarableList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filtarableList = (List<Hero>) results.values;
notifyDataSetChanged();
}
};
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView heroId, heroName;
public CustomViewHolder(View view) {
super(view);
heroId = (TextView) view.findViewById(R.id.heroId);
heroName = (TextView) view.findViewById(R.id.heroName);
}
}
}
below my MainActivity.java
public class MainActivity extends AppCompatActivity {
public LeovegasAdapter leovegasAdapter;
public static final String publicKey = "4089ee37331d8211b080b047c58f6970";
public static final String privateKey = "18ccbcb58fdd12c22821f8b633a06f2b433d16c3";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LeoVegasInterface leoVegasInterface = LeoVegasClient.getApiService();
String ts = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date());
String hash = Hasher.md5(ts + privateKey + publicKey);
Call<LeoVegas> callHeroes = leoVegasInterface.getHeroes(ts, publicKey, hash);
callHeroes.enqueue(new Callback<LeoVegas>() {
#Override
public void onResponse(Call<LeoVegas> call, Response<LeoVegas> response) {
LeoVegas leoVegas = response.body();
Data data = leoVegas.getData();
Hero[] heroes = data.getResults();
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
leovegasAdapter = new LeovegasAdapter(Arrays.asList(heroes));
RecyclerView.LayoutManager eLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(eLayoutManager);
recyclerView.setAdapter(leovegasAdapter);
}
#Override
public void onFailure(Call<LeoVegas> call, Throwable t) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem search = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(search);
search(searchView);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
private void search(SearchView searchView) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
leovegasAdapter.getFilter().filter(newText);
return true;
}
});
}
}
Change your below code
Few changes
Clear the list
Use addAll to fill with the result
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
//Updated code
String charString = charSequence.toString();
ArrayList<Hero> filteredList = new ArrayList<>();
if (charString.isEmpty()) {
filteredList.addAll(filtarableList);
} else {
ArrayList<Hero> filteredList = new ArrayList<>();
for (Hero hero : heros) {
if (hero.getId().toLowerCase().contains(charString) || hero.getName().toLowerCase().contains(charString)) {
filteredList.add(hero);
}
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//Update code
heros.clear();
if (results == null)
heros.addAll(mFilterConversations);
else {
heros.addAll((List<Hero>) results.values);
}
notifyDataSetChanged();
}
};
}
I have a RecyclerView populated by a RoomDatabase and created a SearchView to filter the results if I want to extract a specific set of values from there.
The issues are as follows:
The list gets populated only after I click on the search button, not when the view is opened.
When using the search bar, whatever I write, as long as it is an element from the list, it only shows the element on the first position. If I type something that is not part of the list, it shows the list blank, so this works at least.
This is the code for the Adapter:
public class AbonamenteAdapter2 extends RecyclerView.Adapter<AbonamenteAdapter2.AbonamenteHolder2> implements Filterable {
private List<Abonamente> abonamente;
private List<Abonamente> abonamenteFiltered;
private OnItemClickClickListener listener;
public void setAbonamente(final List<Abonamente> abonamente) {
//this.context = (Context) context;
if (this.abonamente == null) {
this.abonamente = abonamente;
this.abonamenteFiltered = abonamente;
notifyItemChanged(0, abonamenteFiltered.size());
} else {
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
return AbonamenteAdapter2.this.abonamente.size();
}
#Override
public int getNewListSize() {
return abonamente.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return AbonamenteAdapter2.this.abonamente.get(oldItemPosition).getTreatPicked() ==
abonamente.get(newItemPosition).getTreatPicked();
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Abonamente newAbonament = AbonamenteAdapter2.this.abonamente.get(oldItemPosition);
Abonamente oldAbonament = abonamente.get(newItemPosition);
return newAbonament.getTreatPicked() == oldAbonament.getTreatPicked();
}
});
this.abonamente = abonamente;
this.abonamenteFiltered = abonamente;
result.dispatchUpdatesTo(this);
}
}
#NonNull
#Override
public AbonamenteHolder2 onCreateViewHolder (#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new AbonamenteHolder2(view);
}
#Override
public void onBindViewHolder(#NonNull AbonamenteHolder2 holder2, int position) {
Abonamente currentAb = abonamente.get(position);
holder2.treatChosen.setText(currentAb.getTreatPicked());
//holder2.treatChosen.setText(abonamente.get(position).getTreatPicked());
//holder2.treatDisplay = abonamente.getTreatDisplay();
//holder2.treatPrice = abonamente.getPrice();
}
#Override
public int getItemCount() {
if(abonamente != null) {
return abonamenteFiltered.size();
} else {
return 0;
}
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
abonamenteFiltered = abonamente;
} else {
List<Abonamente> filteredList = new ArrayList<>();
for (Abonamente abonament : abonamente) {
if (abonament.getTreatPicked().toLowerCase()
.contains(charString.toLowerCase())) {
filteredList.add(abonament);
}
}
abonamenteFiltered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = abonamenteFiltered;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
abonamenteFiltered = (ArrayList<Abonamente>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class AbonamenteHolder2 extends RecyclerView.ViewHolder {
TextView treatChosen;
public AbonamenteHolder2(View view) {
super(view);
treatChosen = view.findViewById(R.id.element);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
if(listener != null && position != RecyclerView.NO_POSITION) {
listener.onItemClick(abonamente.get(position));
}
}
});
}
}
public interface OnItemClickClickListener {
void onItemClick(Abonamente abonamente);
}
public void setOnItemClickListener(OnItemClickClickListener listener) {
this.listener = listener;
}
}
And this is the code for the activity with the list and search bar. It is triggered by a button press from a different activity:
public class RecyclerList extends AppCompatActivity {
public static final int GET_DATA_LIST = 1;
private SearchView searchView;
private AbonamenteAdapter2 adapter;
private AbonamenteViewModel viewModel;
private String treatDisplay;
private int treatPrice;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_list);
RecyclerView recyclerView = findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
adapter = new AbonamenteAdapter2();
recyclerView.setAdapter(adapter);
viewModel = ViewModelProviders.of(this).get(AbonamenteViewModel.class);
viewModel.getAllEntries().observe(this, new Observer<List<Abonamente>>() {
#Override
public void onChanged(#Nullable List<Abonamente> abonamentes) {
adapter.setAbonamente(abonamentes);
}
});
adapter.setOnItemClickListener(new AbonamenteAdapter2.OnItemClickClickListener() {
#Override
public void onItemClick(Abonamente abonamente) {
Intent intent = new Intent(RecyclerList.this, MainActivity.class);
intent.putExtra(MainActivity.EXTRA_ID, abonamente.getId());
intent.putExtra(MainActivity.EXTRA_CHOICE, abonamente.getTreatPicked());
intent.putExtra(MainActivity.EXTRA_TREAT, abonamente.getTreatDisplay());
intent.putExtra(MainActivity.EXTRA_PRICE, abonamente.getPrice());
startActivityForResult(intent, GET_DATA_LIST);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_bar, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.action_search)
.getActionView();
searchView.setSearchableInfo(searchManager
.getSearchableInfo(getComponentName()));
searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit (String query) {
adapter.getFilter().filter(query);
return false;
}
#Override
public boolean onQueryTextChange(String query) {
adapter.getFilter().filter(query);
return false;
}
});
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_search) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
if(!searchView.isIconified()) {
searchView.setIconified(true);
return;
}
super.onBackPressed();
}
}
I went through the code up and down quite a lot of time and can't seem to figure out what the issue is.
This may be comment for your question but here because of low reputation i need to write answer.
onBindViewHolder method you need to set your filtered list to your Model.
Use
Abonamente currentAb = abonamenteFiltered .get(position);
Instead of
Abonamente currentAb = abonamente.get(position);
I am trying to implement the SearchView within the toolbar. When I try to search my list the original list is always being returned not the new list while trying to do the search.
When I debug it starts to show the new list with the correct amount of items inside of it, but then when its done it just returns the original list size.
When debugging it goes into the publicResults but then doesn't update the adapter. Not sure why it gets the new list but not replace the old one.
Activity that implements the SearchView
public class LoadsActivity extends AppCompatActivity implements SearchView.OnQueryTextListener{
#Inject
Lazy<IMyLoadsRetroService> retroService;
#Inject
IUser user;
public LoadsActivity() {
Injector.INSTANCE.getViewComponent(this).inject(this);
}
public static void startLoadsActivity(Context context) {
Intent loadsIntent = new Intent(context, LoadsActivity.class);
context.startActivity(loadsIntent);
}
#BindView(R.id.recyclerView)
RecyclerView recyclerView;
#BindView(R.id.loadProgressBar)
ProgressBar loadProgressBar;
#BindView(R.id.fab)
FloatingActionButton fab;
LoadAdapter loadAdapter;
private List<IMyLoadSummary> myLoadSummaryList = new ArrayList<>();
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loads);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ButterKnife.bind(this);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
loadAdapter = new LoadAdapter(this, myLoadSummaryList);
recyclerView.setAdapter(loadAdapter);
loadProgressBar.setVisibility(View.VISIBLE);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.startLoadsActivity(LoadsActivity.this);
}
});
retroService.get().getMyLoads().subscribeOn(Schedulers.io()).observeOn(rx.android.schedulers.AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<MyLoadSummary>>() {
#Override
public void onCompleted() {
loadProgressBar.setVisibility(View.GONE);
}
#Override
public void onError(Throwable e) {
Toaster.s(LoadsActivity.this, e.getMessage());
}
#Override
public void onNext(List<MyLoadSummary> myLoadSummaries) {
loadAdapter.setLoadData(myLoadSummaries);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(this);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_search) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
//leaving blank to disable back button
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
loadAdapter.getFilter().filter(newText);
return true;
}
}
Adapter with the Filter
public class LoadAdapter extends RecyclerView.Adapter<LoadAdapter.ViewHolder> implements Filterable {
private Context mContext;
private List<? extends IMyLoadSummary> originalList;
private List<? extends IMyLoadSummary> filteredList;
public LoadAdapter(Context context, List<IMyLoadSummary> list) {
this.mContext = context;
this.originalList = list;
this.filteredList = list;
getFilter();
}
public void setLoadData(List<? extends IMyLoadSummary> mLoadData) {
originalList = mLoadData;
notifyDataSetChanged();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_row, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Gson gson = GsonFactory.getDefault();
String jsonListString = gson.toJson(originalList.get(position));
holder.loadsTextView.setText(jsonListString);
}
#Override
public int getItemCount() {
return originalList.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filteredResults = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<IMyLoadSummary> tempList = new ArrayList<>();
//search content for any number...hopefully
for (IMyLoadSummary myLoadSummary : originalList) {
if (Integer.toString(myLoadSummary.getNumber()).contains(constraint.toString())) {
tempList.add(myLoadSummary);
}
}
filteredResults.count = tempList.size();
filteredResults.values = tempList;
} else {
filteredResults.count = originalList.size();
filteredResults.values = originalList;
}
return filteredResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredList = (List<? extends IMyLoadSummary>) results.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView loadsTextView;
public ViewHolder(View itemView) {
super(itemView);
loadsTextView = (TextView) itemView.findViewById(R.id.loadJSONText);
}
}
}
what i want to suggest is just save the data into android sqlite then run the select * from table_name where name like '%string%"'; query and display it in listview .hope it helps you it is a simple way to do search and fastest too
I have a problem with my application. Actually, I'm totally stuck. I have a list of countries with implemented clicklistener and searchview. In a situation when I click on a given element without searching the list, everything displays correctly and shows information about a given country. But when I search the list and click on the element, the application goes to the information about the random country. I dont know why this is happening. I have no error. Only a warning:
W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
MainActivity
public static final String EXTRA_COUNTRY_NAME = "country_name";
public static final String EXTRA_COUNTRY_REGION = "country_region";
public static final String EXTRA_COUNTRY_NATIVE_NAME = "country_nativename";
public static final String EXTRA_COUNTRY_NAME_LANGUGES= "country_namelanguages";
private RecyclerView recyclerView;
private DataAdapter dataAdapter;
private List<ModelJsona> dataArrayList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
recyclerView=(RecyclerView) findViewById(R.id.card_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
loadJSON();
}
private void loadJSON(){
dataArrayList = new ArrayList<>();
Retrofit retrofit=new Retrofit.Builder().baseUrl("https://restcountries.eu/").addConverterFactory(GsonConverterFactory.create()).build();
RequestInterface requestInterface=retrofit.create(RequestInterface.class);
Call<List<ModelJsona>> call= requestInterface.getJSON();
call.enqueue(new Callback<List<ModelJsona>>() {
#Override
public void onResponse(Call<List<ModelJsona>> call, Response<List<ModelJsona>> response) {
dataArrayList = response.body();
dataAdapter=new DataAdapter(getApplicationContext(),dataArrayList);
recyclerView.setAdapter(dataAdapter);
dataAdapter.setOnitemClickListener(MainActivity.this);
}
#Override
public void onFailure(Call<List<ModelJsona>> call, Throwable t) {
Log.e("Error",t.getMessage());
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
MenuItem search = menu.findItem(R.id.search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(search);
search(searchView);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
private void search(SearchView searchView) {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
dataAdapter.getFilter().filter(newText);
if (dataAdapter !=null)dataAdapter.getFilter().filter(newText);
return true;
}
});
}
#Override
public void onItemClick(int position) {
Intent detailsIntent = new Intent(this,Details.class);
ModelJsona click = dataArrayList.get(position);
detailsIntent.putExtra(EXTRA_COUNTRY_NAME,click.getName());
detailsIntent.putExtra(EXTRA_COUNTRY_REGION,click.getRegion());
detailsIntent.putExtra(EXTRA_COUNTRY_NATIVE_NAME,click.getNativeName());
detailsIntent.putExtra(EXTRA_COUNTRY_NAME_LANGUGES,click.getLanguages().get(0).getName());
startActivity(detailsIntent);
}
}
DataAdapter
private Context context;
private List<ModelJsona> dataList;
private List<ModelJsona> filtr;
private OnitemClickListener mListener;
public interface OnitemClickListener {
void onItemClick (int position);
}
public void setOnitemClickListener (OnitemClickListener listener)
{
mListener=listener;
}
public DataAdapter(Context context, List<ModelJsona> dataList) {
this.context = context;
this.dataList = dataList;
this.filtr= dataList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_row, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.country_name.setText(filtr.get(position).getName());
holder.country_region.setText(filtr.get(position).getRegion());
holder.country_nativename.setText(filtr.get(position).getNativeName());
holder.country_languagename.setText(filtr.get(position).getLanguages().get(0).getName());
}
#Override
public int getItemCount() {
return filtr.size();
}
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
filtr = dataList;
} else {
ArrayList<ModelJsona> listadoprzeszukiwan = new ArrayList<>();
for (ModelJsona wyszukiwarka : dataList) {
if (
wyszukiwarka.getName().contains(charString) ||
wyszukiwarka.getName().toLowerCase().contains(charString) ||
wyszukiwarka.getRegion().contains(charString) ||
wyszukiwarka.getRegion().toLowerCase().contains(charString) ||
wyszukiwarka.getNativeName().contains(charString) ||
wyszukiwarka.getNativeName().toLowerCase().contains(charString) ||
wyszukiwarka.getTopLevelDomain().contains(charString))
{
listadoprzeszukiwan.add(wyszukiwarka);
}
}
filtr = listadoprzeszukiwan;
}
FilterResults wynikiszukania = new FilterResults();
wynikiszukania.values = filtr;
return wynikiszukania;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults wynikiszukania) {
filtr = (ArrayList<ModelJsona>) wynikiszukania.values;
notifyDataSetChanged();
}
};
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView country_name, country_region, country_languagename,country_nativename;
public MyViewHolder(View itemView) {
super(itemView);
country_name = (TextView) itemView.findViewById(R.id.country_name);
country_region = (TextView) itemView.findViewById(R.id.country_region);
country_nativename = (TextView) itemView.findViewById(R.id.country_nativename);
country_languagename= (TextView) itemView.findViewById(R.id.country_languagename);
itemView.setOnClickListener((new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener !=null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
}));
}
}
}
i see that you get the position in filter list refer to different object with same position value in dataList because after filtering filter list become reference to result but still dataList hold all data.
you can replace itemView click listner by this:
itemView.setOnClickListener((new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mListener !=null){
int position = getAdapterPosition();
String name = filtr.get(position).getName();
for (int i=0 ; i <dataList.size() ; i++ ){
if(name.equals(dataList.get(i).getName()){
position = i;
break;
}
}
if (position != RecyclerView.NO_POSITION) {
mListener.onItemClick(position);
}
}
}
}));