RecyclerView item layout not updated - android

I am implementing Edit text with RecyclerView where RecylecerView should update its item and its View when user enter any text in the edit text. It is a very common requirement and i have found tons of solution for this. But i m facing a strange issue that after filtering recylcerView is showing wrong item in the list.
To Illustrate. lets suppose RecylcerView contains items as a,b,c,d and e.
if i search 'c. list shows only one item 'a'. however when i click on this item it is 'c' only. it means only layout not getting updated however values do get updated.
Here is the my implementation.
public class CustomFilter extends Filter{
private CustomFilter(SListRecyclerViewAdapter mAdapter) {
super();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
sData.clear();
final FilterResults results = new FilterResults();
if (constraint.length() == 0) {
sData.addAll(filteredsData);
}
else {
final String filterPattern = constraint.toString().toLowerCase().trim();
for (final S surg: filteredsData) {
if (S.getSUserName().toLowerCase(Locale.getDefault()).contains(filterPattern)) {
sData.add(surg);
}
}
}
results.values = sData;
results.count = sData.size();
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
notifyDataSetChanged();
}

Please see the below example,you have to update the data with result.Please try
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mFilteredData = (ArrayList<String>) results.values;
notifyDataSetChanged();
}

I dont why it is working this way. But i have found a work around.
recyclerView.swapAdapter(sListRecyclerViewAdapter,false);
It is basically swapping the adapter with new one but recycling earlier views. Its not very much optimal but at least workable.

Related

How to show data by object's type in RecyclerAdapter?

I have a list of items with types [a,b,c,d] indicates status of item. When I click on ButtonA I want to show items with types [a,b] in recyclerview, and click on ButtonB show items with types [c,d]. My current solutions is using two list and two adapter, I wonder if there's better approach, thank you.
Its really Easy! I guess in your object model u have Boolean field. You can use Filterable interface.
Just implement it in activity/fragment or viewModel to filter list that u r passing to adapter according to that boolean value or any other criteria inside respective clicklisteners of ur buttons. Its quite simple and intuitive.
Or just share ur code i can do it for you. I really want points ))
The job of an RecyclerAdapter is to show the data you're passing to it.
Unfortunately you don't provide any code, so I assume that the buttons are outside your RecyclerView.
Place a method inside your RecyclerAdapater which you can call from outside. The notifyDataSetChanged() re-runs onBindViewHolder() with your new provided data.
public void updateList(List<YourObjectType> yourObjects) {
this.yourObjects = yourObjects;
notifyDataSetChanged();
}
I solve my problem by implement Filterable interface in adapter. onCreate in activity, after initial adapter to recyclerview, I added this:
adapter.getFilter().filter("u");
Here is my adapter code:
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
if (charSequence.equals("u")) {
List<Transaction> filteredList = new ArrayList<>();
for (Transaction trans : allTrans) {
if (trans.getTr_stt().equalsIgnoreCase("0") ||
trans.getTr_stt().equalsIgnoreCase("2") ||
trans.getTr_stt().equalsIgnoreCase("5")) {
filteredList.add(trans);
}
}
filteredTrans = filteredList;
} else {
List<Transaction> filteredList = new ArrayList<>();
for (Transaction trans : allTrans) {
if (trans.getTr_stt().equalsIgnoreCase("1") ||
trans.getTr_stt().equalsIgnoreCase("3") ||
trans.getTr_stt().equalsIgnoreCase("4")) {
filteredList.add(trans);
}
}
filteredTrans = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = filteredTrans;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
filteredTrans = (ArrayList<Transaction>) filterResults.values;
notifyDataSetChanged();
}
};
}

Dynamically created autocompletetextview shows only selected row after orientation change

I am trying to create an AutoCompleteTextView dynamically for use like a spinner in Android. I have made it work properly with showing the dropdown list on click and on focus change. But when I change orientation after selecting any option, only the selected option is shown in the dropdown after that.
Is there any way to correct this and make it show all the items after orientation change as well? I found one way which is to setText("") everytime but this also clears any selected value which is undesirable.
Any help appreciated!
Recently had a need to do something similar myself. I did this with a custom adapter that overrides the getFilter() which returns null (so that it returns all available values).
public class AutocompleteAdapter extends ArrayAdapter<String> {
public AutocompleteAdapter(Context context, int resource, int textViewResourceId) {
super(context, resource, textViewResourceId);
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
}
};
}
}

CardListView filter

I'm using CardListView from https://github.com/gabrielemariotti/cardslib.
So assume I have simple cardListView with its adapter
CardListView cardListView = (CardListView) findViewById(R.id.card_list);
ArrayList cards = new ArrayList<>();
Card card = new Card(this);
card.setTitle("card text");
CardHeader header = new CardHeader(this);
header.setTitle("card header");
card.addCardHeader(header);
cards.add(card);
CardArrayAdapter adapter = new CardArrayAdapter(this, cards);
cardListView.setAdapter(adapter);
What I want to do is to filter my cardListView according to CardHeader.
The CardArrayAdapter has the method
adapter.getFilter().filter("some text")
But I don't get the idea how it filters cards. In my case, I placed it in
#Override
public boolean onQueryTextChange(String s) {
adapter.getFilter().filter(s);
return true;
}
But it isn't finding any cards in my list, neither by the text I have set in card.setTitle() nor by header.setTitle().
Does anyone know how that works at all?
I really appreciate your taking the time to share your thoughts.
As I can see in the source code, the library doesn't have an implementation for custom filters so first of all you must implement a custom filter similar to this one:
Filter cardFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<Card> tempList = new ArrayList<Card>();
// Where constraint is the value you're filtering against and
// cards is the original list of elements
if(constraint != null && cards!=null) {
// Iterate over the cards list and add the wanted
// items to the tempList
filterResults.values = tempList;
filterResults.count = tempList.size();
}
return filterResults;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// Update your adapter here and notify
cardArrayAdapter.addAll(results.values);
cardArrayAdapter.notifyDataSetChanged();
}
};
After that you have 2 options as far as I can see:
1) Modify the library source code and override the getFilter() method in the CardArrayAdapter or BaseCardArrayAdapter to return an instance of your customFilter
2) Implement the filtering logic directly in your code and only update your adapter when the text from onQueryTextChanged is updated
Here you can find a reference for the code: Custom getFilter in custom ArrayAdapter in android
The arrayAdapter implements Filterable. It works very well with Strings or int for example.
In your case you are working with a Card.
In my opinion first of all you should override the toString() method in your card.
The default getFilter() method in ArrayAdapter uses the object.toString() to filter the list.
If there is not enough you have Implement a custom filter.
Regards,
Javier.

Prevent an AutocompleteTextView from reducing the results

I have an AutoCompleteTextView in my application, but there is a lot more behind every item in the DropDownMenu than what is displayed.
I have my own ArrayAdapter for the AutoCompleteTextView, and when the user starts typing anything the autocompleteTextView starts to reduce the drop down list. This is what I want to change. Every time the user types a new letter, I´m making a new search from the database and would like to show all of those in the drop down menu that pops up, i.e I dont want the autocompleteTextView to reduce the list due to what the user is typing.
So, my question is, is there a way to block an autocompleteTextView from reducing the results, or is it easier to just do an edit text view with my own drop down menu?
Thanks.
Finally, I found a solution that worked perfectly. Just want to share it since I spend a lot of time to get it work.
The AutoCompleteTextView does not have any methods to set no filter, or any way to use a custom filer.
As I wrote I have a custom ArrayAdapter to the AutoCompleteTextView. So what I did was in the ArrayAdapter class, override the function getFilter.
And give the cred to the people posting the answer here.
#Override
public Filter getFilter() {
return new KNoFilter();
}
private class KNoFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence arg0) {
FilterResults result = new FilterResults();
result.values = searchResults;
result.count = searchResults.size();
return result;
}
#Override
protected void publishResults(CharSequence arg0, FilterResults arg1) {
notifyDataSetChanged();
}
}

AutoCompleteTextView - prevent dropdown from closing while calling notifyDataSetChanged

I'm using my own Adapter and my own Filter to populate AutoCompleteTextView. Everything works fine except that every time when I'm calling notifyDataSetChanged dropdown with is closed and then reopens again with new suggestions (which is kind a annoying).
What I'm trying to achieve - is the same behaviour as Google. When you typing word, dropdown just populated with new values (without reopening). Is there any workarounds?
PS
Adapter populated in Filter#publishResults:
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results == null) {
return;
}
mAdapter.clear(); //notifyDataSetChanged is NOT called here
List<?> content = (List<?>) results.values;
final int size = content.size();
for(int i=0; i<size; i++) {
mAdapter.add((City) content.get(i));
}
mAdapter.notifyDataSetChanged();
}

Categories

Resources