Android - List Basics

For Android, the contents of a list are managed in a view named ListView. For the fishing spot example, I'll create a view controller that has a LinearLayout as the top view. I'll then create an XML layout named location_list_view.xml. The contents of the layout file are as follows:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical" >
  7.  
  8. <ListView
  9. android:id="@+id/locationList"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content" >
  12. </ListView>
  13.  
  14. </LinearLayout>

This view is fairly straightforward: The top-level view is a linear layout, and it contains a single sub-view: an instance of ListView identified as locationList.

Note: Unlike iOS, I don't have a toolbar in this view controller. Why? Because Android provides a drop-down menu on every view, so I'll include my navigation controls in the menu.

The contents of LocationListViewController.java are as follows:

  1. package com.crowleyworks.futilefishing.view;
  2.  
  3. public class LocationListViewController extends ViewController {
  4.  
  5. private ListView locationList;
  6. private Context context;
  7. private ArrayAdapter<FishingSpot> adapter;
  8.  
  9. public LocationListViewController(Context context, int layoutId) {
  10. super(context, layoutId);
  11. }
  12.  
  13. public void setLocations(List<FishingSpot> locations) {
  14. adapter.clear();
  15. adapter.addAll(locations);
  16. }
  17.  
  18. public void clearAll() {
  19. adapter.clear();
  20. }
  21.  
  22. @Override
  23. protected void viewDidLoad() {
  24. super.viewDidLoad();
  25.  
  26. locationList = (ListView)view.findViewById(R.id.locationList);
  27. adapter = new ArrayAdapter<FishingSpot>(context, android.R.layout.simple_list_item_1);
  28. locationList.setAdapter(adapter);
  29. }
  30.  
  31. }

Comments:

  • Line 7: Android provides a helper class for managing the contents of a list - ArrayAdapter. Here, I've indicated that the array adapter will manage a collection of FishingSpot objects.
  • Lines 13 - 20: Public helper functions for setting / clearing the contents of the list.
  • Lines 26 - 28: Locate the ListView object, and associate it with a new array adapter. This must be done after the view had been inflated. (If you attempt to do this in the constructor, the list view will not be found.)
  • Line 27: This item merits extra attention. By specifying a base view of android.R.layout.simple_list_item_1, I'm stating that each row of the list will be a simple text label.

To add support for switching views, I've updated the main menu (activity_main.xml) as follows:

  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >
  2.  
  3. <item
  4. android:id="@+id/menu_logout"
  5. android:orderInCategory="100"
  6. android:showAsAction="never"
  7. android:title="@string/menu_logout"/>
  8.  
  9. <item
  10. android:id="@+id/menu_show_list"
  11. android:orderInCategory="101"
  12. android:showAsAction="never"
  13. android:title="@string/menu_show_list"/>
  14.  
  15. <item
  16. android:id="@+id/menu_show_map"
  17. android:orderInCategory="102"
  18. android:showAsAction="never"
  19. android:title="@string/menu_show_map"/>
  20.  
  21. </menu>

In practice, I should have two separate menus: One for when the map view is displayed, and the other for when the list view is displayed. But for simplicity purposes, I've included both menu items on this single menu.

I've also updated Main.java. In onCreate(), I've instantiated a location list view controller:

  1. // ...
  2. locationListVC = (LocationListViewController)getLayoutInflater().inflate(R.layout.location_list_vc, null);
  3. locationListVC.setEventManager(this);
  4. // ...

I've also updated onOptionsItemSelected() as follows:

  1. @Override
  2. public boolean onOptionsItemSelected(MenuItem item) {
  3. switch(item.getItemId()) {
  4. case R.id.menu_logout:
  5. //This cast is completely unnecessary, but I'm doing it to show compatibility with iOS
  6. EventManager eventManager = (EventManager)this;
  7. eventManager.handleEvent(EventManager.EM_REQUEST_LOGOUT, null);
  8. break;
  9.  
  10. case R.id.menu_show_list:
  11. handleEvent(EventManager.EM_NAV_LOCAL_SPOTS_LIST, null);
  12. break;
  13.  
  14. case R.id.menu_show_map:
  15. handleEvent(EventManager.EM_NAV_LOCAL_SPOTS_MAP, null);
  16. break;
  17. }
  18. return super.onOptionsItemSelected(item);
  19. }

The only changes here are the two items to navigate band and forth between the map and list views.

Lastly, I've updated handleEvent() to react to the navigation between the views:

  1. // ...
  2. case EventManager.EM_NAV_LOCAL_SPOTS_MAP:
  3. changeView(fishingMapVC);
  4. LocationLoader ll = new LocationLoader();
  5. ll.setUserId(ffLoginVC.getUserId());
  6. ll.setToken(ffLoginVC.getToken());
  7. ll.setDelegate(fishingMapVC);
  8. AsyncManager.getAsyncManager().submitJob(ll);
  9. break;
  10.  
  11. case EventManager.EM_NAV_LOCAL_SPOTS_LIST:
  12. // For now, simply pull the values from the map view controller
  13. locationListVC.setLocations(fishingMapVC.getAllSpots());
  14. changeView(locationListVC);
  15. break;
  16. // ...

Now that this code is in place, I'm able to navigate from the map view to the list view:


This completes the Android list view example.