I used RecyclerView and custom Adapter in my app ... adapter be implements Filterable for search. How to set high light search text ?
This my code for filterable in custom adapter :
private Filter filterResult = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<Moment> tempList = new ArrayList<>();
if (MOMENT_FILTER != null) {
if (TextUtils.isEmpty(constraint)) {
tempList = (ArrayList<Moment>) MOMENT_FILTER;
} else {
int length = MOMENT_LIST.size();
int i = 0;
while (i < length) {
Moment item = MOMENT_FILTER.get(i);
if (item.getMoment().contains(constraint))
tempList.add(item);
i++;
}
}
}
filterResults.values = tempList;
filterResults.count = tempList.size();
return filterResults;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
MOMENT_LIST = (ArrayList<Moment>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
}
}
};
#Override
public Filter getFilter() {
return filterResult;
}
And this my code in activity for text change (EditText) :
EDT_SEARCH.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s);
}
#Override
public void afterTextChanged(Editable s) {
}
});
result is OK with Sahil answer!
Have a reference of the searchText in your adapter
then in your OnBindViewHolder you can do as
String text = list.get(position).getText(); // Your getter Method
String htmlText = text.replace(searchText,"<font color='#c5c5c5'>"+searchText+"</font>");
// Only searchText would be displayed in a different color.
holder.textView.setText(Html.fromHtml(htmlText );
Related
I have a recyclerview which shows me the list of words and on right side I have bookmark button for each view. Everything works fine but if there is already bookmarked word and if I filter the rycyclerview the image for bookmark does not change. Here you can see in these screenshots:
Before filtering everything is ok as you can see: 3 words are marked
But when I filter the recyclerview another 3 words are beeing marked in that position actually they are not marked
Here is my code for getting bookmark word and comparing with others and marking if they match :
Cursor c = database.rawQuery("SELECT title FROM bookmark WHERE title IN (SELECT title FROM words)", null);
while (c.moveToNext()){
String title = c.getString(0);
if (title.equals(holder.wordsName.getText().toString())){
holder.wordsFav.setImageResource(R.drawable.ic_bookmark_black_24dp);
holder.wordsFav.setTag("clicked");
}
else if (!title.equals(holder.wordsName.getText().toString())){
holder.wordsFav.setImageResource(R.drawable.ic_bookmark_border_black_24dp);
}
}
And here is the code for filtering :
In adapter :
#Override
public Filter getFilter() {
return wordsFilter;
}
private Filter wordsFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Words> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0){
filteredList.addAll(wordsListFull);
}else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (Words words: wordsListFull){
if (words.getWord().toLowerCase().contains(filterPattern)){
filteredList.add(words);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
wordsList = new ArrayList<Words>();
wordsList.clear();
if (wordsList != null){
wordsList.addAll((List) results.values);
}
notifyDataSetChanged();
}
};
And in fragment :
searchWords.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() != 0) {
clearTextBtn.setVisibility(View.VISIBLE);
clearTextBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
searchWords.setText("");
clearTextBtn.setVisibility(View.GONE);
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
});
} else {
clearTextBtn.setVisibility(View.GONE);
}
wordsAdapter.getFilter().filter(s.toString());
}
#Override
public void afterTextChanged(Editable s) {
}
});
Try resetting the image to grey if that particular title is not in the bookmark.
Cursor c = database.rawQuery("SELECT title FROM bookmark WHERE title IN (SELECT title FROM words)", null);
while (c.moveToNext()){
String title = c.getString(0);
if (title.equals(holder.wordsName.getText().toString())){
holder.wordsFav.setImageResource(R.drawable.ic_bookmark_black_24dp);
holder.wordsFav.setTag("clicked");
}else{
holder.wordsFav.setImageResource(R.drawable.default_image);
}
}
I just got lost. I'm populating database using SimpleCursorAdapter to listview. I'd like to filter it with EditText, but every question/code/example/tutorial is simply not working for me. But I've seen many using ArrayAdapter.The question is that, can I populate listview with a SimpleCursorAdapter and them filter it using EditText with an ArrayAdapter?
You must use filter method for filter with edittext.Like above,
kisiText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(s.toString().isEmpty()){
kisiInfoList.clear();
listeyiCek();
adapter = new RehberListAdapter(RehberActivity.this, kisiInfoList);
rehberListView.setAdapter(adapter);
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
adapter.getFilter().filter(s.toString());
}
});
And here is a filter method that your adapter includes,
#Override
public Filter getFilter() {
return new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results.count == 0)
notifyDataSetInvalidated();
else {
kisiList = (List<Kisi>) results.values;
notifyDataSetChanged();
}
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
results.values = kisiList;
results.count = kisiList.size();
} else {
List<Kisi> nPlanetList = new ArrayList<Kisi>();
for (Kisi p : kisiList) {
if (p.getAdSoyad()
.toUpperCase()
.startsWith(constraint.toString().toUpperCase()))
nPlanetList.add(p);
}
results.values = nPlanetList;
results.count = nPlanetList.size();
}
return results;
}
};
}
When you enter text it is filtering and restricting your listView
I display a friend list in a ListView and use a TextWatcher set on an EditText to allow search. This works with 1 limitation (which I am not getting): typing a character correctly filters the list, removing a char however doesn't do anything. The original list is correctly displayed when the input is empty, but the Filter is also supposed to work when a character gets removed, since onTextChanged() gets invoked. Where am I going wrong?
Class (BaseAdapter) fields:
private ArrayList<User> friends;
private ArrayList<User> originalFriendList;
//to keep track of the original list
this.originalFriendList = friends;
Filter class:
private class FriendSearchFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<User> filterList = new ArrayList<User>();
for (User friend : friends) {
if (StringUtils.containsIgnoreCase(friend.getLast_name(), constraint)
|| StringUtils.containsIgnoreCase(friend.getFirst_name(), constraint)) {
filterList.add(friend);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
// the input is empty
results.count = originalFriendList.size();
results.values = originalFriendList;
}
return results;
}
#Override
#SuppressWarnings("unchecked")
protected void publishResults(CharSequence constraint, FilterResults results) {
friends = (ArrayList<User>) results.values;
notifyDataSetChanged();
}
}
TextWatcher:
etSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int start,
int before, int count) {
/* no action required */
}
#Override
public void onTextChanged(CharSequence charSequence, int start, int count, int after) {
if(mFriendListFrag == null || !mFriendListFrag.equals(mFragAdapter.getItem(mViewPager.getCurrentItem())));
mFriendListFrag = (FriendListFragment) mFragAdapter.getItem(mViewPager.getCurrentItem());
mFLAdapter = (FriendListAdapter) mFriendListFrag.getListAdapter();
mFLAdapter.getFilter().filter(charSequence.toString());
Log.e("ON", "TEXT CHANGED");
}
#Override
public void afterTextChanged(Editable editable) {
/* no action required */
}
});
just in case someone has a similar problem: I had to compare the constraint against the original list, and not the "working list" that was overwritten at the time I tried to filter backwards:
for (User friend : originalFriendList)
instead of
for (User friend : friends)
I'm trying to add the search functionality to a ListView that has a custom adapter. When I type something in the EditText it searches and shows the results corectly but if I try to erase what I just wrote it won't come out with the initial list, it will stay with the already filtered list.
Here is the code :
In MainActivity :
private TextWatcher searchTextWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
adapter.getFilter().filter(s.toString());
adapter.notifyDataSetChanged();
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
}
};
In LazyAdapter :
public Filter getFilter() {
return new Filter() {
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
data = (ArrayList<HashMap<String, String>>) results.values;
LazyAdapter.this.notifyDataSetChanged();
}
#Override
protected FilterResults performFiltering(CharSequence constraint) {
ArrayList<HashMap<String, String>> filteredResults = getFilteredResults(constraint);
FilterResults results = new FilterResults();
results.values = filteredResults;
return results;
}
};
}
protected ArrayList<HashMap<String, String>> getFilteredResults(
CharSequence constraint) {
ArrayList<HashMap<String, String>> filteredTeams = new ArrayList<HashMap<String, String>>();
for(int i=0;i< data.size();i++){
if(data.get(i).get(MainActivity.KEY_TITLE).toLowerCase().startsWith(constraint.toString().toLowerCase())){
filteredTeams.add(data.get(i));
}
}
return filteredTeams;
}
What is wrong with my code?
Thank you!
Realize that when you filter you are replacing your unfiltered results in your ArrayList with your filtered results. When you hit backspace to delete characters you are trying to now filter based on your already filtered list which is why your results won't change. You will need to keep a reference to your original data set that doesn't have any filter applied to it and always filter using that, but never change/replace it.
I'm working on an autocompletetextview that will work off of a key value system, and am trying to find out what I need to do to make publishResults work, as the results param being passed to publishResults here is correct in the debugger, however I have no idea what it should correspond to or how to cause it to display the results, can anyone help? the creation of this object is in another file, and looks like this:
autoCompleteBox.setAdapter(new AutoCmpAdapter(this, android.R.layout.simple_dropdown_item_1line));
and the rest of the code is as follows:
public class AutoCmpAdapter extends ArrayAdapter<String> implements Filterable {
protected Filter filter;
protected ArrayList<String> items;
protected ArrayList<String> res;
String lWds[] = { "HOMER", "TOM" };
String sWds[] = { "SIMPSON", "JONES" };
public AutoCmpAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
filter = new PhysFilter();
res = new ArrayList<String>();
}
public Filter getFilter() {
return filter;
}
private class PhysFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults f = new FilterResults();
res.clear();
if (constraint != null) {
ArrayList<String> res = new ArrayList<String>();
for (int x = 0; x < sWds.length; x++) {
if (sWds[x].toUpperCase().startsWith(constraint.toString().toUpperCase())) {
res.add(lWds[x]);
}
}
f.values = res.toArray();
f.count = res.size();
}
return f;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
Log.println(Log.INFO, "Results", "FOUND");
notifyDataSetChanged();
} else {
Log.println(Log.INFO, "Results", "-");
notifyDataSetInvalidated();
}
}
}
}
First of all don't use String array.
to work for key value pair you can adjust your If statement..
try this in your onCreate
AutoCompleteTextView mAutoCompleteTextView;
ArrayList<String> lWds = new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mAutoCompleteTextView=(AutoCompleteTextView)findViewById(R.id.testAutoComplete);
final AutoCmpAdapter adapter= new AutoCmpAdapter(this, android.R.layout.simple_dropdown_item_1line,lWds);
mAutoCompleteTextView.setAdapter(adapter);
mAutoCompleteTextView.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
adapter.getFilter().filter(s);
}
});
}
and adapter class like
public class AutoCmpAdapter extends ArrayAdapter<String> implements Filterable {
protected Filter filter;
protected ArrayList<String> items;
protected ArrayList<String> res;
String sWds[] = { "SIMPSON", "JONES" };
public AutoCmpAdapter(Context context, int textViewResourceId,ArrayList<String> listData) {
super(context, textViewResourceId,0,listData);
filter = new PhysFilter();
res = new ArrayList<String>();
}
public Filter getFilter() {
return filter;
}
private class PhysFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults f = new FilterResults();
res.clear();
if (constraint != null) {
ArrayList<String> res = new ArrayList<String>();
for (int x = 0; x < sWds.length; x++) {
if (sWds[x].toUpperCase().contains(constraint.toString().toUpperCase())) {
res.add(sWds[x]);
}
}
f.values = res;//.toArray();
f.count = res.size();
}
return f;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results.count > 0) {
Log.println(Log.INFO, "Results", "FOUND");
lWds.clear();
lWds.addAll((ArrayList<String>) results.values);
notifyDataSetChanged();
} else {
Log.println(Log.INFO, "Results", "-");
notifyDataSetInvalidated();
}
}
}
}