问题
I have been trying to implement a simple search to a listView which I have been able to populate using Volley but all to no avail till date. Thanks to @Dhaval Patel who has been of greet help. But the issue I am having now is that when I search, the ListView refuse to change content thus making the whose search useless in the program
Below is my code:
public class MainActivity extends Activity {
private ListView mList;
private List<Movie> movieList = new ArrayList<Movie>();
EditText inputSearch;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
mList = (ListView) findViewById(R.id.list);
inputSearch = (EditText) findViewById(R.id.inputSearch);
adapter = new CustomListAdapter(this, movieList);
mList.setAdapter(adapter);
//SEARCH TEXTCHANGE
inputSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
MainActivity.this.adapter.getFilter().filter(cs.toString());
//FLAGS Cannot resolve method 'getFilter()' here
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
}
Also this is the code in my CustomListAdapter class
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Movie> movieItems;
private String[] bgColors;
private List<String>originalData = null;
private List<String>filteredData = null;
private ItemFilter mFilter = new ItemFilter();
ImageLoader imageLoader = MyApplication.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
}
@Override
public int getCount() {
return movieItems.size();
}
@Override
public Object getItem(int location) {
return movieItems.get(location);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row_image, null);
if (imageLoader == null)
imageLoader = MyApplication.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView.findViewById(R.id.thumbnail);
TextView serial = (TextView) convertView.findViewById(R.id.serial);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView rating = (TextView) convertView.findViewById(R.id.rating);
TextView genre = (TextView) convertView.findViewById(R.id.genre);
TextView year = (TextView) convertView.findViewById(R.id.releaseYear);
// getting movie data for the row
Movie m = movieItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
// title
title.setText(m.getTitle());
// rating
rating.setText("Rating: " + String.valueOf(m.getRating()));
// genre
String genreStr = "";
for (String str : m.getGenre()) {
genreStr += str + ", ";
}
genreStr = genreStr.length() > 0 ? genreStr.substring(0,
genreStr.length() - 2) : genreStr;
genre.setText(genreStr);
// release year
year.setText(String.valueOf(m.getYear()));
String color = bgColors[position % bgColors.length];
serial.setBackgroundColor(Color.parseColor(color));
return convertView;
}
public Filter getFilter() {
return mFilter;
}
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<String> list = originalData;
int count = list.size();
final ArrayList<String> nlist = new ArrayList<String>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i);
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(filterableString);
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredData = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
}
}
So can someone please tell me what I am not doing right. Thanks in advance
回答1:
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<Movie> list = movieItems;
int count = list.size();
final ArrayList<Movie> nlist = new ArrayList<Movie>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i).getName();
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(list.get(i));
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
movieItems= (ArrayList<String>) results.values;
notifyDataSetChanged();
}
}
回答2:
It seems you don't use your filteredData in the adapter.
So when you call notifiyDataSetChanged there is no change in the data use to fill the ListView.
The publishResults method should change the data used to populate the views, ie for you the movieItems list.
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<Movie> list = originalMovieItems;
int count = list.size();
final ArrayList<Movie> nlist = new ArrayList<Movie>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i).getName();//or whatever you want to filter on
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(list.get(i));
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
movieList = (ArrayList<Movie>) results.values;
notifyDataSetChanged();
}
}
So to keep the movie list unchanged (not the one you display but the one you filter on), you should add a originalMovieList field to your adapter class and modify the constructor as following.
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
this.originalMovieList = movieItems;
}
回答3:
This is how i was able to solve the misery of my searching code.
on my MainActivity
public class MainActivity extends Activity {
private List<Movie> currentMovieList = new ArrayList<Movie>();
private List<Movie> originalMovieList = new ArrayList<Movie>();
private CustomListAdapter adapter;
private ListView mList;
// Search EditText
EditText inputSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_main);
inputSearch = (EditText) findViewById(R.id.inputSearch);
adapter = new CustomListAdapter(this, currentMovieList);
mList.setAdapter(adapter);
inputSearch.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
String filterString = cs.toString().toLowerCase();
Log.e("TAG", "filterString:" + filterString);
currentMovieList.clear();
if (TextUtils.isEmpty(filterString)) {
currentMovieList.addAll(originalMovieList);
}
String filterableString;
for (Movie movie : originalMovieList) {
//search from the title field
if (movie.getTitle().toLowerCase().contains(filterString)) {
currentMovieList.add(movie);
}
//search from the year field
else if (String.valueOf(movie.getYear()).toLowerCase().contains(filterString))
{
currentMovieList.add(movie);
}
//search from the rating field
else if (String.valueOf(movie.getRating()).toLowerCase().contains(filterString))
{
currentMovieList.add(movie);
}
//search from the genre field
else if (movie.getGenre().toString().toLowerCase().contains(filterString))
{
currentMovieList.add(movie);
}
}
adapter.notifyDataSetChanged();
//FLAGS Cannot resolve method 'getFilter()' here
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,int arg3) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
} }
And ADD this to your CustomListAdapter
public class CustomListAdapter extends BaseAdapter implements Filterable {
private Activity activity;
private LayoutInflater inflater;
private List<String>originalData = null;
// private List<String>filteredData = null;
private List<Movie> movieItems;
private List<Movie> originalMovieList;
private String[] bgColors;
ImageLoader imageLoader = MyApplication.getInstance().getImageLoader();
private ItemFilter mFilter = new ItemFilter();
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
// this.originalMovieList = movieItems;
this.originalMovieList = new ArrayList<Movie>(movieItems);
bgColors = activity.getApplicationContext().getResources().getStringArray(R.array.movie_serial_bg);
}
//Add Below Method
public void reloadData(){
this.originalMovieList = new ArrayList<Movie>(movieItems);
notifyDataSetChanged();
}
@Override
public int getCount() {
return movieItems.size();
}
@Override
public Object getItem(int location) {
return movieItems.get(location);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row_image, null);
if (imageLoader == null)
imageLoader = MyApplication.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView.findViewById(R.id.thumbnail);
TextView serial = (TextView) convertView.findViewById(R.id.serial);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView rating = (TextView) convertView.findViewById(R.id.rating);
TextView genre = (TextView) convertView.findViewById(R.id.genre);
TextView year = (TextView) convertView.findViewById(R.id.releaseYear);
// getting movie data for the row
Movie m = movieItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
// title
title.setText(m.getTitle());
// rating
rating.setText("Rating: " + String.valueOf(m.getRating()));
// genre
String genreStr = "";
for (String str : m.getGenre()) {
genreStr += str + ", ";
}
genreStr = genreStr.length() > 0 ? genreStr.substring(0,
genreStr.length() - 2) : genreStr;
genre.setText(genreStr);
// release year
year.setText(String.valueOf(m.getYear()));
String color = bgColors[position % bgColors.length];
serial.setBackgroundColor(Color.parseColor(color));
return convertView;
}
public Filter getFilter() {
return mFilter;
}
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
//results.values = nlist;
//results.count = nlist.size();
results.values = originalMovieList;
results.count = originalMovieList.size();
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//filteredData = (ArrayList<String>) results.values;
//movieItems = (ArrayList<Movie>) results.values;
movieItems.clear();
movieItems.addAll((ArrayList<Movie>) results.values);
notifyDataSetChanged();
}
}
}
Now thats a WRAP. Thanks to @DhavalPatel That Guy is an Android Guru.
He made all this happen.
-Happy Coding
来源:https://stackoverflow.com/questions/33525787/search-functionality-to-listview-using-baseadapter-not-populating-list-on-search