Continued from: Android Lists: ListActivity and ListView I – Basic Usage
You’ve got a functioning list of stock ticker symbols now; however, it’s just a list of symbols and nothing more. Let’s explore how to add a static stock quote to each of the ticker symbols.
First, you can design the layout of how the stock ticker and quote should appear in the list. This is accomplished by creating a new layout file under res\layout. The following shows a simple row layout with two TextView
s placed side-by-side horizontally:
="1.0"="utf-8"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="@+id/ticker_symbol" />
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="@+id/ticker_price" />
</LinearLayout>
While you used the ArrayAdapter
in the previous part, you can’t use that adapter here since it only accepts a layout that contains a single TextView
. One of the easiest and most flexible ways to use the layout that was just created is to create your own adapter by making a new class that extends from ArrayAdapter
.
To do this, you can start by making a data class that will hold the stock quote information. This class will be used as the type parameter to ArrayAdapter
when you create your new adapter class. I’ve provided a basic class below that holds the stock ticker and quote, along with getters and setters.
package com.austinrasmussen.stockviewer;
public class StockQuote {
private String tickerSymbol;
private double quote;
public StockQuote(String tickerSymbol, double quote) {
this.tickerSymbol = tickerSymbol;
this.quote = quote;
}
public void setTickerSymbol(String tickerSymbol) {
this.tickerSymbol = tickerSymbol;
}
public String getTickerSymbol() {
return tickerSymbol;
}
public void setQuote(double quote) {
this.quote = quote;
}
public double getQuote() {
return quote;
}
}
Now that you have a class to hold the stock quote data, you can create the custom adapter that will use that class. The key behind extending ArrayAdapter
is to override the ArrayAdapter.getView(…)
method. If this isn’t done, you will run into the limitation of the ArrayAdapter
class that requires you to provide it with a layout that only contains a single TextView
(i.e. java.lang.IllegalStateException: ArrayAdapter
requires the resource ID to be a TextView
). I’ve put together an adapter class that will fulfill the requirements for this part of the series.
package com.austinrasmussen.stockviewer;
import java.util.List;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class StockQuoteAdapter extends ArrayAdapter {
private final Activity activity;
private final List stocks;
public StockQuoteAdapter(Activity activity, List objects) {
super(activity, R.layout.stock_quote_list_item , objects);
this.activity = activity;
this.stocks = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
StockQuoteView sqView = null;
if(rowView == null)
{
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.stock_quote_list_item, null);
sqView = new StockQuoteView();
sqView.ticker = (TextView) rowView.findViewById(R.id.ticker_symbol);
sqView.quote = (TextView) rowView.findViewById(R.id.ticker_price);
rowView.setTag(sqView);
} else {
sqView = (StockQuoteView) rowView.getTag();
}
StockQuote currentStock = stocks.get(position);
sqView.ticker.setText(currentStock.getTickerSymbol());
sqView.quote.setText(currentStock.getQuote().toString());
return rowView;
}
protected static class StockQuoteView {
protected TextView ticker;
protected TextView quote;
}
}
The only step left to do is combine the stock quote data with the newly created StockQuoteAdapter
class. This will be done in the main StockList
activity class that we started in the previous part of this series. All that needs to be done here is to create an ArrayList
of StockQuote
objects, which will be used in constructing the StockQuoteAdapter
. The String
array creation and list adapter code is now replaced with the following:
List stocks = new ArrayList();
stocks.add(new StockQuote("MSFT", 24.78));
stocks.add(new StockQuote("ORCL", 34.02));
stocks.add(new StockQuote("AMZN", 180.13));
stocks.add(new StockQuote("ERTS", 19.73));
setListAdapter(new StockQuoteAdapter(this, stocks));
You can now run the application and it will be presented with the following:
Well, that looks… quite ugly. You’ll also notice that we’ve lost the font formatting when using the simple_list_item_1
layout. This is because simple_list_item_1
had some simple formatting applied to the single TextView
in the layout.
In the next part, I’ll go over layout and formatting in some more detail. This will assist in readability and help clean up the view.
Final Code
package com.austinrasmussen.stockviewer;
import java.util.ArrayList;
import java.util.List;
import android.app.ListActivity;
import android.os.Bundle;
public class StockList extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List stocks = new ArrayList();
stocks.add(new StockQuote("MSFT", 24.78));
stocks.add(new StockQuote("ORCL", 34.02));
stocks.add(new StockQuote("AMZN", 180.13));
stocks.add(new StockQuote("ERTS", 19.73));
setListAdapter(new StockQuoteAdapter(this, stocks));
}
}
package com.austinrasmussen.stockviewer;
public class StockQuote {
private String tickerSymbol;
private Double quote;
public StockQuote(String tickerSymbol, Double quote) {
this.tickerSymbol = tickerSymbol;
this.quote = quote;
}
public void setTickerSymbol(String tickerSymbol) {
this.tickerSymbol = tickerSymbol;
}
public String getTickerSymbol() {
return tickerSymbol;
}
public void setQuote(double quote) {
this.quote = quote;
}
public Double getQuote() {
return quote;
}
}
package com.austinrasmussen.stockviewer;
import java.util.List;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class StockQuoteAdapter extends ArrayAdapter {
private final Activity activity;
private final List stocks;
public StockQuoteAdapter(Activity activity, List objects) {
super(activity, R.layout.stock_quote_list_item , objects);
this.activity = activity;
this.stocks = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
StockQuoteView sqView = null;
if(rowView == null)
{
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.stock_quote_list_item, null);
sqView = new StockQuoteView();
sqView.ticker = (TextView) rowView.findViewById(R.id.ticker_symbol);
sqView.quote = (TextView) rowView.findViewById(R.id.ticker_price);
rowView.setTag(sqView);
} else {
sqView = (StockQuoteView) rowView.getTag();
}
StockQuote currentStock = stocks.get(position);
sqView.ticker.setText(currentStock.getTickerSymbol());
sqView.quote.setText(currentStock.getQuote().toString());
return rowView;
}
protected static class StockQuoteView {
protected TextView ticker;
protected TextView quote;
}
}
="1.0"="utf-8"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="@+id/ticker_symbol" />
<TextView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="@+id/ticker_price" />
</LinearLayout>
="1.0"="utf-8"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@android:id/list" />
</LinearLayout>