I am configuring a resource in my app to search in a Listview using a custom Adapter. I using an EditText to type the string and passing the text to Adapter on addTextChangedListener Event, but it is not working.
I configure the adapter with "implements Filterable" and enable Listview with ".setTextFilterEnabled(true)", but doesn´t work.
I saw that I must implement "public Filter getFilter()" but I have no idea how can I do that.
When I type some words in EditText, like "cel" or "12" the filter goes in action, but the result is always the same: The first two items in Listview, no matter what is into the Listview (the content of listview is random).
Below a snippet of my Fragment Activity:
public class VideosFragment extends Fragment {
private ListView listView;
private ArrayList<String> idVideo = new ArrayList<>();
private ArrayList<String> titleVideo = new ArrayList<>();
private ArrayList<String> descVideo = new ArrayList<>();
private ArrayList<String> urlVideo = new ArrayList<>();
private ArrayList<String> channelTitle = new ArrayList<>();
private ArrayList<String> canalTitle = new ArrayList<>();
private ArrayList<String> canalId = new ArrayList<>();
private CustomFiltraCanaisAdapter customFiltraCanaisAdapter;
private EditText editText;
CustomVideoAdapter customVideoAdapter;
public VideosFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_videos, container, false);
// Configure Listview
listView = (ListView)view.findViewById(R.id.listView_videos);
//Create search parameters
editText = (EditText) view.findViewById(R.id.searchList);
listView.setTextFilterEnabled(true);
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
String text = editText.getText().toString().toLowerCase(Locale.getDefault());
VideosFragment.this.customVideoAdapter.getFilter().filter(text);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
and below my CustomAdapter:
public class CustomVideoAdapter extends ArrayAdapter<String> implements Filterable {
private final Activity context;
private final ArrayList<String> videoTitle;
private final ArrayList<String> videoDesc;
private final ArrayList<String> videoId;
private final ArrayList<String> channelTitle;
private final ArrayList<String> imgurl;
public CustomVideoAdapter(Activity context, ArrayList<String> videoTitle,
ArrayList<String> videoId,
ArrayList<String> channelTitle,
ArrayList<String> imgurl,
ArrayList<String> videoDesc) {
super(context, R.layout.custom_lista_videos, videoTitle);
// TODO Auto-generated constructor stub
this.context = context;
this.videoTitle = videoTitle;
this.videoDesc = videoDesc;
this.videoId = videoId;
this.channelTitle = channelTitle;
this.imgurl = imgurl;
}
public View getView(int position,View view,ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View rowView=inflater.inflate(R.layout.custom_lista_videos, null,true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.txtVideoTitle);
ImageView imgPhoto = (ImageView) rowView.findViewById(R.id.imgPhoto);
TextView txtChannelTitle = (TextView) rowView.findViewById(R.id.txtChannelTitle);
TextView txtVideoId = (TextView) rowView.findViewById(R.id.txtVideoId);
TextView txtVideoDesc = (TextView) rowView.findViewById(R.id.txtVideoDesc);
txtTitle.setText(videoTitle.get(position));
Picasso.with(context).load(imgurl.get(position)).into(imgPhoto);
txtChannelTitle.setText(channelTitle.get(position));
txtVideoId.setText(videoId.get(position));
txtVideoDesc.setText(videoDesc.get(position));
return rowView;
};
What is missing?
After some helps I trying to create (and use) a Model Class, but I still have no progress because I did not figure out how can I must change my code on "CustomAdapter" to use correctly this code.
My Model Class is below:
public class FilteredVideoAdapter {
private ArrayList<String> storedVideoTitle = null;
private ArrayList<String> storedVideoDesc = null;
private ArrayList<String> storedVideoId = null;
private ArrayList<String> storedChannelTitle = null;
private ArrayList<String> storedImgurl = null;
public FilteredVideoAdapter(){
}
public ArrayList<String> getStoredVideoTitle() {
return storedVideoTitle;
}
public void setStoredVideoTitle(ArrayList<String> storedVideoTitle) {
this.storedVideoTitle = storedVideoTitle;
}
public ArrayList<String> getStoredVideoDesc() {
return storedVideoDesc;
}
public void setStoredVideoDesc(ArrayList<String> storedVideoDesc) {
this.storedVideoDesc = storedVideoDesc;
}
public ArrayList<String> getStoredVideoId() {
return storedVideoId;
}
public void setStoredVideoId(ArrayList<String> storedVideoId) {
this.storedVideoId = storedVideoId;
}
public ArrayList<String> getStoredChannelTitle() {
return storedChannelTitle;
}
public void setStoredChannelTitle(ArrayList<String> storedChannelTitle) {
this.storedChannelTitle = storedChannelTitle;
}
public ArrayList<String> getStoredImgurl() {
return storedImgurl;
}
public void setStoredImgurl(ArrayList<String> storedImgurl) {
this.storedImgurl = storedImgurl;
}
public FilteredVideoAdapter withFilteredVideoAdapter(
ArrayList<String> storedVideoTitle,
ArrayList<String> storedVideoDesc,
ArrayList<String> storedVideoId,
ArrayList<String> storedChannelTitle,
ArrayList<String> storedImgurl){
this.storedVideoTitle = storedVideoTitle;
this.storedVideoDesc = storedVideoDesc;
this.storedVideoId = storedVideoId;
this.storedChannelTitle = storedChannelTitle;
this.storedImgurl = storedImgurl;
return this;
}
}
This is what you have to do inside your adapter, you might need to do some tweaks:-
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
// If the constraint (search string/pattern) is null
// or its length is 0, i.e., its empty then
// we just set the `values` property to the
// original contacts list which contains all of them
if (constraint == null || constraint.length() == 0) {
results.values = videoTitle;;
results.count = videoTitle.size();
}
else {
// Some search copnstraint has been passed
// so let's filter accordingly
ArrayList<String> filteredTitle = new ArrayList<String>();
// We'll go through all the title and see
// if they contain the supplied string
for (String c : string) {
if (string.toUpperCase().contains( constraint.toString().toUpperCase() )) {
// if `contains` == true then add it
// to our filtered list
filteredTitle.add(c);
}
}
// Finally set the filtered values and size/count
results.values = filteredTitle;
results.count = filteredTitle.size();
}
// Return our FilterResults object
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mList = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
};
}
Hope this will help you.