Reputation: 1505
While there are many questions relating to this subject here on stackoverflow, I can say I've looked through many of them and tried different things, but still I don't get it to work.
I have a ListView which I populate with a custom Adapter of custom classes I've created. I also have a spinner, which I'm trying to use as a filter for the list.
This is my simplified code, I removed everything that isn't relevant here make it clearer as possible, also simplifying some of the variable names:
public class OnlineNavActivity extends AppCompatActivity {
private ListView tourList;
private ArrayList<Tour> toursData;
private Spinner filterSpinner;
private TourAdapter tourAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tours_online);
// Set up the spinner
filterSpinner = (Spinner) findViewById(R.id.country_spinner);
addItemsToSpinner();
filterSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedCountry = (String) parent.getItemAtPosition(position);
Log.i(LOG_TAG, selectedCountry);
if (!selectedCountry.equals(Data.ALL_COUNTRIES)) { // if string does not equal to "All Countries"
toursData = Data.listByFilter(selectedCountry);
}
else {
toursData = Data.dataList;
}
tourAdapter = new TourAdapter(getApplicationContext(), toursData);
tourAdapter.notifyDataSetChanged();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
toursData = Data.dataList;
tourAdapter = new TourAdapter(getApplicationContext(), toursData);
tourAdapter.notifyDataSetChanged();
}
});
// Assign all of the data to the array at first, will change by filter spinner
toursData = Data.dataList;
// Generate the list view
tourList = (ListView) findViewById(R.id.online_nav_list);
tourAdapter = new TourAdapter(this ,toursData);
tourList.setAdapter(tourAdapter);
}
(The Data.listByFilter()
is the method I've created in a different class which returns an ArrayList with the applied filter).
The problem is that when I click on the spinner and select an item - nothing happenes.
I have tried to use tourAdapter.clear()
and then adding the items with add
command but that didn't work (The ListView became empty for any selection in the spinner).
Adding items to the adapter worked as items were added to the ListView and updated there, but this is not what I need, just something that worked while I was trying to figure this out.
Thanks.
Edit:
After trying many things, I finally find a solution. While it doesn't seem like an optimal solution, since I declare a new TourAdapter
on every spinner action, this is the only one that worked for me.
What I did, is declaring a new TourAdapter
and then calling setAdapter
.
Also, I have left onNothingSelected
as an empty method. This is what it looks like (all the other code remains the same):
filterSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedCountry = (String) parent.getItemAtPosition(position);
Log.i(LOG_TAG, selectedCountry);
if (!selectedCountry.equals(Data.ALL_COUNTRIES)) { // if string does not equal to "All Countries"
toursData = Data.listByFilter(selectedCountry);
Log.i(LOG_TAG, "first country is" + toursData.get(0).getCountry());
}
else {
toursData = Data.dataList;
}
tourAdapter = new TourAdapter(getApplicationContext() ,toursData);
tourList.setAdapter(tourAdapter);
//tourAdapter.notifyDataSetChanged();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Upvotes: 0
Views: 222
Reputation: 11
The problem is you are creating a new adapter (new TourAdapter(...) within onItemSelected and onNothingSelected methods) every time you click on the Spinner and this adapter is not linked to your list.
In this two methods, instead of creating a new one, you should get the adapter the list already has (you set it with tourList.setAdapter), create a method on the adapter that set the new elements on it and update the list with notifyDataSetChange.
String selectedCountry = (String) parent.getItemAtPosition(position);
Log.i(LOG_TAG, selectedCountry);
if (!selectedCountry.equals(Data.ALL_COUNTRIES)) {
toursData = Data.listByFilter(selectedCountry);
} else {
toursData = Data.dataList;
}
tourAdapter = ((TourAdapter) tourList.getAdapter()).setNewElements(toursData);
tourAdapter.notifyDataSetChanged();
The setNewElements should be a method in the adapter like this:
public void setNewElements(List<Tour> newElementsList) {
this.myElements = newElementsList;
}
***** Edit *****
String selectedCountry = (String) parent.getItemAtPosition(position);
Log.i(LOG_TAG, selectedCountry);
toursData.clear();
if (!selectedCountry.equals(Data.ALL_COUNTRIES)) {
toursData.addAll(Data.listByFilter(selectedCountry));
}
else {
toursData.addAll(Data.dataList);
}
tourAdapter.notifyDataSetChanged();
Upvotes: 1