Android 列表:ListActivity 和 ListView II – 自定义适配器和列表项视图





5.00/5 (4投票s)
续接: Android 列表:ListActivity 和 ListView I。
续接: Android 列表:ListActivity 和 ListView I – 基本用法
你现在已经拥有了一个可以正常运行的股票代码列表;但是,它只是一个符号列表,仅此而已。让我们探讨如何为每个股票代码添加一个静态股票报价。
首先,你可以设计股票代码和报价在列表中显示的方式。这可以通过在 res\layout 下创建一个新的布局文件来完成。以下显示了一个简单的行布局,其中包含两个 TextView
,水平并排放置。
<?xml version="1.0" encoding="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>
虽然你在上一部分使用了 ArrayAdapter
,但你不能在这里使用该适配器,因为它只接受包含单个 TextView
的布局。创建自定义适配器的一种最简单和最灵活的方法是通过创建一个继承自 ArrayAdapter
的新类。
为此,你可以首先创建一个数据类,该类将保存股票报价信息。该类将用作创建新的适配器类时 ArrayAdapter
的类型参数。我提供了一个基本的类,它保存股票代码和报价,以及 getter 和 setter。
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;
}
}
现在你已经拥有了一个用于保存股票报价数据的类,你可以创建将使用该类的自定义适配器。扩展 ArrayAdapter
的关键是重写 ArrayAdapter.getView(…)
方法。如果未这样做,你将遇到 ArrayAdapter
类的限制,该限制要求你提供只包含单个 TextView
的布局(即 java.lang.IllegalStateException: ArrayAdapter
requires the resource ID to be a TextView
)。我准备了一个适配器类,它将满足本系列这部分的要求。
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)
{
// Get a new instance of the row layout view
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.stock_quote_list_item, null);
// Hold the view objects in an object,
// so they don't need to be re-fetched
sqView = new StockQuoteView();
sqView.ticker = (TextView) rowView.findViewById(R.id.ticker_symbol);
sqView.quote = (TextView) rowView.findViewById(R.id.ticker_price);
// Cache the view objects in the tag,
// so they can be re-accessed later
rowView.setTag(sqView);
} else {
sqView = (StockQuoteView) rowView.getTag();
}
// Transfer the stock data from the data object
// to the view objects
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;
}
}
剩下的唯一一步是将股票报价数据与新创建的 StockQuoteAdapter
类结合起来。这将在我们从本系列上一部分开始的主 StockList
活动类中完成。这里需要做的就是创建一个 StockQuote
对象的 ArrayList
,它将在构造 StockQuoteAdapter
时使用。字符串数组创建和列表适配器代码现在被替换为以下内容
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));
现在你可以运行该应用程序,它将显示以下内容
好吧,看起来……相当难看。你还会注意到,在使用 simple_list_item_1
布局时,我们失去了字体格式。这是因为 simple_list_item_1
对布局中的单个 TextView
应用了一些简单的格式。
在下一部分中,我将更详细地介绍布局和格式。这将有助于提高可读性并清理视图。
最终代码
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 {
/** Called when the activity is first created. */
@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)
{
// Get a new instance of the row layout view
LayoutInflater inflater = activity.getLayoutInflater();
rowView = inflater.inflate(R.layout.stock_quote_list_item, null);
// Hold the view objects in an object,
// so they don't need to be re-fetched
sqView = new StockQuoteView();
sqView.ticker = (TextView) rowView.findViewById(R.id.ticker_symbol);
sqView.quote = (TextView) rowView.findViewById(R.id.ticker_price);
// Cache the view objects in the tag,
// so they can be re-accessed later
rowView.setTag(sqView);
} else {
sqView = (StockQuoteView) rowView.getTag();
}
// Transfer the stock data from the data object
// to the view objects
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;
}
}
<?xml version="1.0" encoding="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>
<?xml version="1.0" encoding="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>