Lists Presentation

Agenda

  • ListViews and adapters
  • Customized ListView items

Lists on screen

  • The problem
    • Memory intensive to create many views on screen
    • In a list, most views are not even displayed on screen
    • Dynamically creating a view for each data item not good
  • The solution
    • Virtual list
    • Only create views for the currently visible data items
    • Reuse view objects for different data items when scrolling
    • Both Android and iOS have platform solutions to this

ListView

  • Define ListView element in xml layout
    • Define xml layout for each item inside list
  • Store data items in memory
    • Or in a SQLite database
  • Connect the two with an adapter
    • Abstraction of multiple data items
    • ListView handles different types of data the same way

ListView

  • Just like any other view in the layout xml file
    • Often expanded vertically to fill out remaining area
    • No items can be specified in xml
  • Add ListView to layout
    <ListView android:id="@+id/list"
      android:layout_width="match_parent" 
      android:layout_height="match_parent" />
    

ArrayList

  • Manage an ArrayList of all data items
    • Using singular values like string for each item
      ArrayList<String> simpleData = new ArrayList<String>();
      simpleData.add("Some name here");
      
    • Using complex values like objects of your class
      ArrayList<Item> complexData = new ArrayList<Item>();
      Item item = new Item();
      item.name = "Some name here";
      complexData.add(item);
      

ArrayAdapter

  • Specify
    • Context - this when in Activity
    • Data source - the ArrayList
    • Xml layout to display each item in data source
    • Optional identifier(s) where to output data value
  • Create an ArrayAdapter with the type of item
    ArrayAdapter<String> simpleAdapter = new ArrayAdapter<String>(this,
      android.R.layout.simple_list_item_1, simpleData);
    
    ArrayAdapter<Item> complexAdapter = new ArrayAdapter<Item>(this,
      R.layout.my_own_item_layout, complexData);
    

Connecting the adapter to the ListView

  • Get a reference to it in Java code and set its Adapter
    ListView list = (ListView) findViewById(R.id.list);
    list.setAdapter(adapter);
    

Built-in layouts for list adapters

  • A single TextView
    • android.R.layout.simple_list_item_1
    • Each item's toString is used to get text
  • Two TextViews, title and subtitle
    • android.R.layout.simple_list_item_2
    • Requires items and maps to define text to show in each

Custom layout for list adapters

  • You provide the layout xml for each item
  • You control the item view generation
  • When you need more control than showing a single String
  • Create your own class derived from ArrayAdapter
  • Override getView method to build the user interface for each item
    • Use a pattern for dealing with reusable item views and the whole virtualization that the ListView and Adapter provides
  • Access and modify whatever you like in each item

Custom item XML layout

  • Example (not all attributes shown for clarity)
    <LinearLayout>
      <ImageView android:id="@+id/icon" />
      <TextView android:id="@+id/title" />
      <TextView android:id="@+id/hours" />
    </LinearLayout>
    

Custom Adapter class

  • Inherit from an existing Adapter
    • Define a constructor
    • Override the getView method that creates each layout item for the list
  • Your custom class
    class MyAdapter extends ArrayAdapter<String> {
        public MyAdapter(Context context, ArrayList<String> data) {
            super(context, R.layout.item, data);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
        }
    }
    

Custom layout items

  • Inflate the item layout
    @Override
    public View getView(int position, View view, ViewGroup parent) {
      if (view == null) {
        view = MainActivity.this.getLayoutInflater().inflate(R.layout.item, null);
      }
      String item = getItem(position);
      TextView text = (TextView) view.findViewById(R.id.text);
      text.setText(item);
      return view;
    }
    

ListView events

  • Events fired for the list item as a whole
    • Create and specify in onCreate when activity starts
  • OnItemClickListener
    • When user touches on an item in the list
  • OnItemLongClickListener
    • When user touches and holds on for a period of time, on an item in the list
  • Events fired from specific views inside the list item
    • Create and specify inside of getView

ListView event handler

  • Implement event handler
    ListView list = (ListView) findViewById(R.id.list);
    list.setOnItemClickListener(new OnItemClickListener() {
      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
      }
    });
    
  • Arguments
    • AdapterView<?> is the adapter for the ListView
    • View is the visual element container for the particular item that was clicked
    • int is the position of the item that was clicked (first is zero)
    • long is the identifier of a SQLite database table row, if a CursorAdapter was used

Button clicks in items

  • Button with onClick in item layout
    • Single onClick called in Activity for all items
    • Use View argument to find out which item
  • From an item view to a position
    ListView _list;
    ArrayAdapter<String> _adapter;
    public void onClick(View btn) {
      int position = _list.getPositionForView();
      String value = _adapter.getItem(position);
    }
    

Updating the data

  • The data source may change as much as needed
  • Tell adapter about change and update the list
    • Call notifyDataSetChanged on the adapter
    • Store the adapter as a class member, or retrieve it from the list
  • Example
    ListView list = (ListView) findViewById(R.id.list);
    ArrayAdapter<String> adapter = (ArrayAdapter<String>) list.getAdapter();
    adapter.notifyDataSetChanged();
    

Extra features