Reputation: 5
Is this a right way to filter an ArrayList
containing text from strings.xml? I get nothing in the ListView
when I enter some characters inside SearchView
.
public class SearchActivity extends AppCompatActivity {
private ListView searchList;
private SearchListAdapter searchListAdapter;
private ArrayList<listContents> listArray;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
searchList = (ListView)findViewById(R.id.searchList);
listContents listC[] = new listContents[]{
new listContents(R.string.UtrujjTitle,R.string.UtrujjContent,R.drawable.image1),
new listContents(R.string.AruzzTitle,R.string.AruzzContainer,R.drawable.image2),
new listContents(R.string.ArzTitle,R.string.ArzContainer,R.drawable.image3)
};
listArray = new ArrayList<>(Arrays.asList(listC));
searchListAdapter = new SearchListAdapter(getApplicationContext(),listArray);
searchList.setAdapter(searchListAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search, menu);
final SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.searchable).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
ArrayList<listContents> filtered = new ArrayList<listContents>();
for (int i = 0; i < listArray.size() ; i++){
String title = String.valueOf(listArray.get(i).getTitleList());
String contain = String.valueOf(listArray.get(i).getContentList());
if (title.contains(newText) || contain.contains(newText)){
listContents contents = new listContents(listArray.get(i).getTitleList(),
listArray.get(i).getContentList(),listArray.get(i).getImageList());
filtered.add(contents);
}
searchListAdapter = new SearchListAdapter(getApplicationContext(),filtered);
searchList.setAdapter(searchListAdapter);
}
return false;
}
});
return true;
}
}
Adapter class
public class SearchListAdapter extends ArrayAdapter<listContents> {
private Context context;
private listContents[] listContentsList;
private ArrayList<listContents> lister;
public SearchListAdapter(Context context, ArrayList<listContents> list ) {
super(context,0,list);
this.context = context;
this.lister = list;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
listContents listContents = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.listresults, parent, false);
}
TextView title = (TextView) convertView.findViewById(R.id.listTitle);
title.setText(listContents.getTitleList());
TextView content = (TextView)convertView.findViewById(R.id.listContain);
content.setText(listContents.getContentList());
ImageView imageView = (ImageView)convertView.findViewById(R.id.listImage);
imageView.setImageResource(listContents.getImageList());
return convertView;
}
}
Upvotes: 0
Views: 3963
Reputation: 1917
Here,
ArrayList channelData = new ArrayList<>(); ArrayList filtered_channelData = new ArrayList<>();
edt_search_channel.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { }
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (filtered_channelData != null) {
filtered_channelData.clear();
Log.d("mytag", "list is clear" + filtered_channelData.size());
}
for (int i = 0; i < channelData.size(); i++) {
if (channelData.get(i).getName().toLowerCase().trim()
.contains(edt_search_channel.getText().toString().toLowerCase().trim())) {
filtered_channelData.add(channelData.get(i));
HashSet hs = new HashSet();
hs.addAll(filtered_channelData);
filtered_channelData.clear();
filtered_channelData.addAll(hs);
}
}
channelAdapter = new ChannelAdapter(context, filtered_channelData, dialogChannel);
rv_channel.setAdapter(channelAdapter);
Log.d("mytag", "filtered_skill_listing size in out of for loop" + filtered_channelData.size());
channelAdapter.notifyDataSetChanged();
}
@Override
public void afterTextChanged(Editable editable) {
if (edt_search_channel.getText().toString().equals("")) {
channelAdapter = new ChannelAdapter(context, channelData, dialogChannel);
rv_channel.setAdapter(channelAdapter);
channelAdapter.notifyDataSetChanged();
}
}
});
Upvotes: 0
Reputation: 1200
ArrayAdapter
has filtering logic built in to the class, so you don't really need to create a new adapter each time a query is made, you can just run the filter method using the query string. Try this:
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
searchListAdapter.getFilter().filter(newText);
return true;
}
});
The ArrayAdapter
filter internally uses the toString
value of your class when performing the comparison, so you will need to override toString
for listContents
, e.g. to something like this:
@Override
public String toString() {
return getTitleList() + " - " + getContentList();
}
Edit:
I noticed that you're passing in the resource ids instead of the actual string to the listContents
class. Values such as R.string.UtrujjTitle
are just integers which are identifiers for an actual string.
Assuming that getTitleList()
isn't returning the actual string, but merely returns the resource id, then the above toString
method will not work. Whichever filtering approach you take, you'll need to obtain the actual string from the resource id to do the comparison.
You're options, then, are either to change your code to store the actual String inside listContents
instead of the resource id, or pass in a Context
reference.
With a Context
reference, you can make the following change to toString()
:
@Override
public String toString() {
return context.getString(getTitleList()) + " - " + context.getString(getContentList());
}
Edit 2:
Looking over your filtering code, the bug most likely is due to the following 2 lines:
String title = String.valueOf(listArray.get(i).getTitleList());
String contain = String.valueOf(listArray.get(i).getContentList());
Instead, you probably meant to do (assuming the getters are returning a resource id) is:
String title = getString(listArray.get(i).getTitleList());
String contain = getString(listArray.get(i).getContentList());
However, there's most likely going to be more overhead reinstantiating an adapter over reusing the same one while using its filter functionality. But if you want to keep what you already have, this change may fix it.
Upvotes: 2