102
ListView

ListView. What is a list view? A ViewGroup that displays scrollable items

Embed Size (px)

Citation preview

ListView

What is a list view?

• A ViewGroup that displays scrollable items.

3 Parts of a ListView

• The ListView itself – aka a ViewGroup

• List items– Each row/item in the list. Each item is a layout

consisting of a View or ViewGroup. • Data for each item

ListItem

• Since the ListItem can be a ViewGroup, we have the power to display very simple or extremely complex layouts for each item.– A TextView– A TextView and ImageView– A TextView and CheckBox– A TextView and Button– A TextView, ImageView, CheckBox, Button, and

RatingBar, etc

Where does the data come from?

• ListViews receive data via Adapters.

• The Adapter behaves as the middleman between the data source and the ListView.

The job of an Adapter

• The Adapter fetches data from the source.

• Creates the layout that represents each list item.

• Takes the data fetched from the source places it into the list item layout.

• Returns a list item to the ListView.

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

Bill and Ted’s Excellent…

Teen Wolf

Honey I shrunk…

Texas Chainsaw Mas…

Pupper Master

Bill and Ted…

ListView

Data source for Adapters

1. Arrays

2. Content Provider– Used to get Calendar and Contact info from

phone.

3. Database Cursor

Types of Adapters

• ArrayAdapter– Works with Arrays– Can handle any Java Object as input– Uses the .toString() method of the JavaObject to

obtain text for list item.

• SimpleCursorAdapter– Works with a Content Provider and Database

Cursor

Hello World ListView Example

Layout Resource<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" >

<ListView android:id="@+id/mylist" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView>

</LinearLayout>

Codepackage com.example.lecture2;

import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;

public class ListLecture extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.list_lecture);

ListView listView = (ListView) findViewById(R.id.mylist);String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };

// First parameter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// Assign adapter to ListViewlistView.setAdapter(adapter);

}}

Codepackage com.example.lecture2;

import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;

public class ListLecture extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.list_lecture);

ListView listView = (ListView) findViewById(R.id.mylist);String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };

// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// Assign adapter to ListViewlistView.setAdapter(adapter);

}}

Inflate the layoutfor the Activity.

Codepackage com.example.lecture2;

import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;

public class ListLecture extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.list_lecture);

ListView listView = (ListView) findViewById(R.id.mylist);String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };

// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// Assign adapter to ListViewlistView.setAdapter(adapter);

}}

Extract the ListView from the layout

Create data source for list

Codepackage com.example.lecture2;

import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;

public class ListLecture extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.list_lecture);

ListView listView = (ListView) findViewById(R.id.mylist);String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };

// First parameter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// Assign adapter to ListViewlistView.setAdapter(adapter);

}}

Create the Adapter

Creating Adapter: Parameter 1// First paramenter - Context

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,

android.R.id.text1, values);

1

Creating Adapter: Parameter 2// First paramenter - Context// Second parameter - Layout for the list item or row

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,

android.R.id.text1, values);

2

Creating Adapter: Parameter 3// First paramenter - Context// Second parameter - Layout for the list item or row// Third parameter - ID of the TextView to which the data is written

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,

android.R.id.text1, values);

3

Creating Adapter: Parameter 4// First paramenter - Context// Second parameter - Layout for the list item or row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of data

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,

android.R.id.text1, values);

4

Codepackage com.example.lecture2;

import android.app.Activity;import android.os.Bundle;import android.widget.ArrayAdapter;import android.widget.ListView;

public class ListLecture extends Activity {

@Overridepublic void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);setContentView(R.layout.list_lecture);

ListView listView = (ListView) findViewById(R.id.mylist);String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" };

// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of dataArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, values);

// Assign adapter to ListViewlistView.setAdapter(adapter);

}} Set adapter to ListView to bind data

Mystery Layout and ID???// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of data

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,

android.R.id.text1, values);

Mystery Layout and ID???// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of data

//Accessing resource from our projectsetContentView(R.layout.list_lecture);

//Accessing resource from Android Platform (Accessible to all apps)ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_list_item_1, android.R.id.text1, values);

Layouts provided by Android Platform

• The Android Platform provides built-in XML layouts.

• These built-in layouts are accessible to all applications.

• Makes it even easier to use common layouts!

android.R.layout.simple_list_item_1

<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="fill_parent"  android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" android:paddingLeft="6dip" android:minHeight="?android:attr/listPreferredItemHeight">

Android Platform Built-in Layouts

• http://developer.android.com/reference/android/R.layout.html

View the XML for Built-in Layouts

• http://www.netmite.com/android/mydroid/frameworks/base/core/res/res/layout/

Resource ID for each Layouts

• The resource ID for the TextView inside each built in Android layout is the same:

android:id="@android:id/text1"

Not so mysterious Layout and ID???

// First paramenter - Context// Second parameter - Layout for the row// Third parameter - ID of the TextView to which the data is written// Forth - the Array of data

//Accessing resource from our projectsetContentView(R.layout.list_lecture);

//Accessing resource from Android Platform (Accessible to all apps)ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,

android.R.layout.simple_list_item_1, android.R.id.text1, values);

ListView Example Result

AdapterView

• ListView derives from AdapterView

• AdapterViews are Views that use Adapters.

• There are several other AdapterView subclasses that behave much like ListView.

Subclasses of AdapterView

1. AdapterViewFlipper2. GridView3. Spinner4. Gallery5. StackView6. ExpandableListView

Back to ListView

• How to add event handling?

Adding Click Handler

• To react to clicks in the list, set an onItemClickListener on your ListView.

onItemClickListener Example// Assign adapter to ListViewlistView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view,

int position, long id) {Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

}});

onItemClick Parameters

parent The AdapterView where the click happened.

view The view within the AdapterView that was clicked (this will be a view provided by the adapter)

position The position of the view in the adapter.

id The row id of the item that was clicked.

onItemClick(AdapterView<?> parent, View view, int position, long id)

onItemClickListener Example// Assign adapter to ListViewlistView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view,

int position, long id) {Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

}});

OnItemClickListener Result

Would you like some Toast?

Toast Message

• A Toast provides simple feedback about an operation in a small popup.

• The Toast only fills enough space to wrap the text of the message.

• The Toast displays on top of the current activity, but the activity is still visible and interactive.

Toast Example

Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

1

1. Context

Toast Example

Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

1. Context2. String message to print

2

Toast Example

Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

1. Context2. String message to print3. Duration to display Toast

3

Toast Example

Toast.makeText(getApplicationContext(), "Click ListItem Number " + position, Toast.LENGTH_LONG) .show();

1. Context2. String message to print3. Duration to display Toast4. Method to make the Toast show itself

4

Specify Toast Duration

• The Toast Object has two predefined durations.1. LENGTH_LONG ~3.5 seconds

2. LENGTH_SHORT ~2 seconds

• You can’t specify a custom duration.

Specify Location of Toasts

• A standard toast notification appears near the bottom of the screen, centered horizontally.

• You can change this position with the setGravity(int, int, int) method.

• This accepts three parameters: a Gravity constant, an x-position offset, and a y-position offset.

Toast Location example

toast.setGravity(Gravity.TOP|Gravity.LEFT, 0, 0);

Modifying Your List

• How do I add more items?• How can I add a set of items?• How do I clear all items?

ArrayAdapter Helper Methods

• add(T Object) – Adds the specified object to the end of the array.

• addAll(T… items) – Adds the specified items at the end of the array.

• clear() – Remove all elements from the list

ArrayAdapter Helper Methods

• notifyDataSetChanged() – notification that the underlying data has been changed and that the View should refresh itself.

• remove(T Object) – Removes the specified object from the array.

ArrayAdapter Helper Methods

• getItem(int position) – gets Object at specified position in adapter.

• getPosition(T item) – Returns the position of the specified item in the array.

ArrayAdapter Abilities

• Filtering – filter data by a certain constraint– Only show data that begins with the letter “S.”

• Sorting – sort the contents of the adapter using a specified comparator. – Sort by alpha A-Z, alpha Z-A, etc.

ListActivity

ListActivity

• Useful when your Activity only supports a single list.

• ListActivity was designed to simplify the handling of ListViews.

Standard ListActivity

• ListActivity has a default layout that consists of a single full-screen list in the center of the screen.

• ListActivity does not require that you assign it a layout resource via setContentView(). ListActivity handles that for you.

Custom ListActivity

• If you want to include more views than just a ListView in your Activity, you may call setContentView() yourself with your own layout.

• In this case, your layout MUST contain a ListView with the android:id attribute set to @android:id/list

ListActivity helper methods

• ListActivity provides helper methods for – List Item Click events– Setting the ListView’s adapter

ListActivity click handling

• When using a ListActivity, you don’t need to implement an onItemClickListener().

• ListActivity already implements one for you.

• Simply @Override ListActivity’s onListItemClick() to handle list click events.

Setting the ListView’s adapter with ListActivity

• ListActivity provides the setListAdapter() method.

• Internally calls setAdapter() on the ListView for the ListActivity.

ListActivity Exampleimport android.app.ListActivity;import android.os.Bundle;import android.widget.ArrayAdapter;

public class MyListActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] values = new String[] { "Android", "iPhone", "WindowsMobile", "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2" }; ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, values); setListAdapter(adapter); }}

ListView Recycling

Beginner’s initial impression of ListView

• The ListView probably creates a view for each list item and only displays the item currently on screen.

Array<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master", "Land Before Time", "TMNT", "Weird Science", "Goonies", "Total Recall", "Howard the duck", "Kindgergarden Cop", "Bloodsport", "Universal Soldier", "Ernest scared stupid", "Dumb and Dumber", "Breakfast Club" };

Bill and Ted’s Excellent…

Teen Wolf

Honey I shrunk…

Texas Chainsaw Mas…

Pupper Master

Land Before Time

TMNT

Weird Science

Goonies

ListView

ListItem

ListView recycles its items

• To cut down on View Objects, a ListView will only allocate enough Item Views to “roughly” fill the size of a ListView.

• When a Item gets scrolled off the ListView, its view will be reused by a new Item that is scrolling on to the ListView.

Array<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master", "Land Before Time", "TMNT", "Weird Science", "Goonies", "Total Recall", "Howard the duck", "Kindgergarden Cop", "Bloodsport", "Universal Soldier", "Ernest scared stupid", "Dumb and Dumber", "Breakfast Club" };

Bill and Ted’s Excellent…

Teen Wolf

Honey I shrunk…

Texas Chainsaw Mas…

Pupper Master

Land Before Time

ListView Recyling

• Automatically taken care of by the ListView when using a standard ArrayAdapter.

• However, if you implement your own Adapter you’ll have to do a little work.

How Adapters work internally

Quick look at ArrayAdapter.java

• Lets look at how the ArrayAdapter class does the following:1. Creates list item Views2. Recycles list item Views

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

ListView

getView(int position, View convertView, ViewGroup parent)

1 1. Position of the list item we want.

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

ListView

getView(int position, View convertView, ViewGroup parent)

1. If the ListView has any recycled Views it will send one of these recycled Views for the Adapter to use; else, it will send null.

2

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

ListView

getView(int position, View convertView, ViewGroup parent)

33. The parent of the list item; in this case, the ListView.

Getting First Item for ListArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

ListView

getView(0, null, this)

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

Bill and Ted’s Excellent…

ListView

getView(0, null, this)

How did the Adapter generate the list item View?

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

The layout resource we passed into the Adapter’s constructor,Aka the layout we requested to use for each list item.

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

If convertView is null, we need to createa new View. Inflate the layout resource to do this.

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

If convertView isn’t null, we need can reuse therecyled view.

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

Find the TextView within the list item layout.

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

Fetch the data (stored in the Adapter) that is associated with this list item position.

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

ArrayAdapter only sets the text for the TextView included in the list item layout resource. So extractthe String from Object and set the TextView’s text.

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

Bill and Ted’s Excellent…

ListView

getView(0, null, this)

public View getView(int position, View convertView, ViewGroup parent) { return createViewFromResource(position, convertView, parent, mResource); }

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource) { View view; TextView text;

if (convertView == null) { view = mInflater.inflate(resource, parent, false); } else { view = convertView; }

try { if (mFieldId == 0) { // If no custom field is assigned, assume the whole resource is a TextView text = (TextView) view; } else { // Otherwise, find the TextView field within the layout text = (TextView) view.findViewById(mFieldId); } } catch (ClassCastException e) { Log.e("ArrayAdapter", "You must supply a resource ID for a TextView"); throw new IllegalStateException( "ArrayAdapter requires the resource ID to be a TextView", e); }

T item = getItem(position); if (item instanceof CharSequence) { text.setText((CharSequence)item); } else { text.setText(item.toString()); }

return view; }

Code taken from ArrayAdapter.java

0 null ListView

Bill & Ted’s…

How an Adapter WorksArray<String> mMovies = { "Bill and Ted's Excellent Adventures", "Teen

Wolf", "Honey I shrunk the kids", "Texas Chainsaw Massacre", "Puppet Master" }

Adapter

Bill and Ted’s Excellent…

ListView

getView(0, null, this)

Implementing your own adaper

Custom Adapter

• The default look and feel of the Android ListView is not very attractive.

• Also, remember the default action of an ArrayAdapter is to call the toString() method on the data object it contains.– This means your list will change the text on the list

item and nothing else.

Getting creative with Custom Adapters

• With Custom Adapters, you can use your own layout to make lists more interesting.

• You can make the list items look any way you want.

• You can make the list item have more data than just simple text.

Steps for create a custom adapter

1. Extend an existing Adapter class

2. Define a constructor

3. @Override the Adapter’s getView() method. – Use this to inflate custom list items– Use this to populate the item with more data than just what comes

from toString().

Extend an existing Adapter

• Create a class that extends1. BaseAdapter2. ArrayAdapter3. SimpleCursorAdapter

• You’ll want to extend an existing adapter because they provide quite a bit of functionality that we don’t want to rewrite ourselves.

Custom Adapter Examplepublic class MoviePosterAdapter extends ArrayAdapter<String> {

}

Define a constructor

• Use the constructor for the following:– Specify the layout to be used by Adapter for list

items– Get access/save a reference to the adapter’s data

source– Initialize any startup logic for your adapter

Custom Adapter Constructorpublic class MoviePosterAdapter extends ArrayAdapter<String> {

public MoviePosterAdapter(Context context) {

super(context, R.layout.movie_list_item, R.id.text, context.getResources().getStringArray(R.array.movie_list)); }}

1

1. Implementing a constructor that takes only a context and forces it to use a layout defined in my application’s resources.

Custom Adapter Constructorpublic class MoviePosterAdapter extends ArrayAdapter<String> {

public MoviePosterAdapter(Context context) {

super(context, R.layout.movie_list_item, R.id.text, context.getResources().getStringArray(R.array.movie_list)); }}

2

2. Make the Adapter use the movie_list_item layout.

Custom Adapter Constructorpublic class MoviePosterAdapter extends ArrayAdapter<String> {

public MoviePosterAdapter(Context context) {

super(context, R.layout.movie_list_item, R.id.text, context.getResources().getStringArray(R.array.movie_list)); }}

3. Point the Adapter to use the TextView, defined in the movie_list_item layout, whose id is equal to R.id.text

3

Custom Adapter Constructorpublic class MoviePosterAdapter extends ArrayAdapter<String> {

public MoviePosterAdapter(Context context) {

super(context, R.layout.movie_list_item, R.id.text, context.getResources().getStringArray(R.array.movie_list)); }}

4. Pass the data used by the adapter into the super.

4

Using the Custom Adapter on a ListView

public class MyListWithCustomAdapterActivity extends ListActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MoviePosterAdapter mpAdapter = new MoviePosterAdapter(this); setListAdapter(mpAdapter); }

}

Using this constructor will setup the Adapter using the Constructor methoddefined in my custom adapter.

Custom Adapter Example Result

Must @Override getView()

• The ArrayAdapter class only knows how to update each list item’s text.

• If your list item uses any other data, your getView() needs to implement logic to properly set up the list item to display the necessary data.

Basic getView() implementationpublic class MoviePosterAdapter extends ArrayAdapter<String> { public MoviePosterAdapter(Context context) { super(context, R.layout.movie_list_item,

R.id.text, context.getResources(). getStringArray(R.array.movie_list));

}

@Override public View getView(int position, View convertView, ViewGroup parent) { View listItem = super.getView(position, convertView, parent); return listItem; }}

MoviePosterAdapter Example

• Implement the Adapter to keep track of which list items are checked.

• The Adapter needs to keep a reference to some object that keeps track of this.

• The getView() needs to use that object and determine if it should check an item or not.

Add a HashMap to keep track of checked items

public class MoviePosterAdapter extends ArrayAdapter<String> { private HashMap<Integer, Boolean> mMovieHash = new HashMap<Integer, Boolean>();

public MoviePosterAdapter(Context context) {super(context, R.layout.movie_list_item,

R.id.text, context.getResources().getStringArray(R.array.movie_list)); mMovieHash.put(1, true);

}

@Overridepublic View getView(int position, View convertView, ViewGroup parent) { View listItem = super.getView(position, convertView, parent); CheckBox box = (CheckBox) listItem.findViewById(R.id.checkbox); boolean contains = mMovieHash.containsKey(position); if (contains && mMovieHash.get(position)) { box.setChecked(true); } else { box.setChecked(false); } return listItem;}

}

ListView with MoviePosterAdapter