I'm trying to implement a two level DrawerLayout. As a baseline, I'm using the Google planet example from http://developer.android.com/training/implementing-navigation/nav-drawer.html . So I'd like to extend this example, such that selecting a planet from the list of planets, replaces the planet list with a list of cities on that planet (mostly blank except for Earth - I'm still fleshing out my data :-) ).
I figured there are three approaches I could take:-
So trying option 3 (is this the best approach?), in my DrawerItemClickListener I do the following ...
arrayAdapter.clear();
arrayAdapter.addAll(arrayListOfCities);
arrayAdapter.notifyDataSetChanged();
mDrawerList.invalidateViews();
mDrawerList.forceLayout();
mDrawerList.refreshDrawableState();
but it doesn't seem to work, ie the list of planets doesn't get replaced by a list of cities.
Is my approach correct?, and if so, how do I get the list to refresh?
Replace the ListView
There's really no need for that.
Keep the ListView, but replace its ArrayAdapter
This would be the easiest to implement. First, add the following string arrays (city names) to res/values/strings.xml:
<string-array name="mercury_array">
<item>Undiscovered City 1 (Mercury)</item>
<item>Undiscovered City 2 (Mercury)</item>
<item>Undiscovered City 3 (Mercury)</item>
<item>Undiscovered City 4 (Mercury)</item>
</string-array>
<string-array name="venus_array">
<item>Undiscovered City 1 (Venus)</item>
<item>Undiscovered City 2 (Venus)</item>
<item>Undiscovered City 3 (Venus)</item>
<item>Undiscovered City 4 (Venus)</item>
</string-array>
<string-array name="earth_array">
<item>New York</item>
<item>Hong Kong</item>
<item>New Delhi</item>
<item>London</item>
</string-array>
<string-array name="mars_array">
<item>Undiscovered City 1 (Mars)</item>
<item>Undiscovered City 2 (Mars)</item>
<item>Undiscovered City 3 (Mars)</item>
<item>Undiscovered City 4 (Mars)</item>
</string-array>
<string-array name="jupiter_array">
<item>Undiscovered City 1 (Jupiter)</item>
<item>Undiscovered City 2 (Jupiter)</item>
<item>Undiscovered City 3 (Jupiter)</item>
<item>Undiscovered City 4 (Jupiter)</item>
</string-array>
<string-array name="saturn_array">
<item>Undiscovered City 1 (Saturn)</item>
<item>Undiscovered City 2 (Saturn)</item>
<item>Undiscovered City 3 (Saturn)</item>
<item>Undiscovered City 4 (Saturn)</item>
</string-array>
<string-array name="uranus_array">
<item>Undiscovered City 1 (Uranus)</item>
<item>Undiscovered City 2 (Uranus)</item>
<item>Undiscovered City 3 (Uranus)</item>
<item>Undiscovered City 4 (Uranus)</item>
</string-array>
<string-array name="neptune_array">
<item>Undiscovered City 1 (Neptune)</item>
<item>Undiscovered City 2 (Neptune)</item>
<item>Undiscovered City 3 (Neptune)</item>
<item>Undiscovered City 4 (Neptune)</item>
</string-array>
Create a method loadContentList(int)in MainActivity. This is the method that will be called on item click for the main list:
private void loadContentList(int position) {
setTitle(mPlanetTitles[position]);
String[] content;
switch(position) {
case 0:
content = getResources().getStringArray(R.array.mercury_array);
break;
case 1:
content = getResources().getStringArray(R.array.venus_array);
break;
case 2:
content = getResources().getStringArray(R.array.earth_array);
break;
case 3:
content = getResources().getStringArray(R.array.mars_array);
break;
case 4:
content = getResources().getStringArray(R.array.jupiter_array);
break;
case 5:
content = getResources().getStringArray(R.array.saturn_array);
break;
case 6:
content = getResources().getStringArray(R.array.uranus_array);
break;
case 7:
content = getResources().getStringArray(R.array.neptune_array);
break;
default:
content = getResources().getStringArray(R.array.neptune_array);
}
// Change ListView's adapter
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, content));
// Change OnItemClickListener // CityItemClickListener is defined below
mDrawerList.setOnItemClickListener(new CityItemClickListener());
}
Since we want to update the ListView when a planet item is clicked, we will change the method body of DrawerItemClickListener and call the newly added loadContentList(int):
/* The click listner for ListView in the navigation drawer */
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//selectItem(position);
loadContentList(position);
}
}
We will need another OnItemClickListener to change fragments when a city is clicked. :
private class CityItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// This is the method that was being called on planet click
// in the original example. Implementation of it is up to you
selectItem(position);
}
}
Keep the ListView and the ArrayAdapter, but replace the adapter's data
Define the ArrayAdapter:
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
---------> private ArrayAdapter<String> mAdapter;
In MainActivity's onCreate(Bundle):
ArrayList<String> planetList = new ArrayList<String>();
planetList.addAll(Arrays.asList(mPlanetTitles));
mAdapter = new ArrayAdapter<String>(this,
R.layout.drawer_list_item, planetList);
// set up the drawer's list view with items
mDrawerList.setAdapter(mAdapter);
We have to pass an ArrayList to avoid UnsupportedOperationException when calling mAdapter.clear().
Change loadContentList(int) to the following:
private void loadContentList2(int position) {
setTitle(mPlanetTitles[position]);
String[] content;
switch(position) {
....
....
}
ArrayList<String> cityList = new ArrayList<String>();
cityList.addAll(Arrays.asList(content));
mAdapter.clear();
mAdapter.addAll(cityList);
// update
mAdapter.notifyDataSetChanged();
// Change on item click listener
mDrawerList.setOnItemClickListener(new CityItemClickListener());
}
The CityItemClickListener and DrawerItemClickListener will stay the same as before. The only change is: we're not creating a new ArrayAdapter on planet list item click.
You'll need to figure out a way (a button perhaps) for the user to go back to planet list from city view.
I would also suggest that you look into ExpandableListView. It might solve your problem more elegantly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With