Translated by:AcerWang    原文出自:customizing-android-listview-items-with-custom-arrayadapter 

背景介绍

  对于现实世界中的商业移动应用来说,Android的ListView默认的界面外观不是非常有吸引力。它只是使用了内部的TextView控件,在每个ListView的行(Row)里面传递了一个简单的字符串而已。大多数应用,你会想要创建出富含图形界面和呈现给用户视觉体验良好的应用。幸运地是,ListView 是一个非常强大的控件,由于有可定制的item 布局的帮助,它可以被定制从而轻松地适应你的需求。在本文中,我将向你展示怎样创建一个定制的ListView  Item(有图标,自定义的header布局)以及怎样使用定制的ArrayAdapter将他们联系起来。我也会向你展示一些性能优化的小方法来优化你的ListView控件的内存占用。下面用一个例子来展示:

      图1. 天气图                            图2. 布局结构图

            

   一、项目布局

  在Eclipse中,创建一个新的Android项目,使用默认的Activity和main.xml布局文件。在main.xml文件中,声明一个ListView控件。

 main.xml文件:
1 <?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"
android:background="#FFFFFF"> <ListView
android:id="@+id/listView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>

  上面的代码,使用了简单的线性布局方式,内部垂直排列。声明了一个ListView,占据整个父容器,他的android.layout_width和android.layout_width的属性都为fill_parent。ListView有一个唯一的id:listView1,在MainActivity中将用来引用ListView控件。

  为了创建定制的header,先在你的工程中创建一个新的xml布局文件:listview_header_row.xml,在里面声明一个TextView控件,属性值见下面的代码。将会创建出一个白色字体,蓝色背景的header。

 listview_header_row.xml文件:
<?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:id="@+id/txtHeader"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:textStyle="bold"
android:textSize="22dp"
android:textColor="#FFFFFF"
android:padding="10dp"
android:text="Weather Photos"
android:background="#336699" /> </LinearLayout>

  为了创建定制的ListView的行样式,先在你的工程中创建另一个xml布局文件:listview_item_row.xml。Android 会将这个文件的内容传递给每个ListView的item,你将可以自由的声明任何你想添加进里面的控件。本文中,我使用了一个ImageView来显示天气图标和一个TextView来显示该条item的主题。下面是listview_item_row.xml文件的代码:

 listview_item_row.xml文件:
<?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"
android:padding="10dp"> <ImageView android:id="@+id/imgIcon"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" /> <TextView android:id="@+id/txtTitle"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:textStyle="bold"
android:textSize="22dp"
android:textColor="#000000"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" /> </LinearLayout>

  本文中,我下载了一些32 X 32像素的PNG格式的图标。如果你愿意,你也可以使用你自己的图标。准备好你的图标,放到你工程的drawable-mdpi文件目录下。接下来,在工程中新建一个java类,命名为Weather.java,这个类将用于创建一个定制的ArrayAdapter来绑定对象到ListView中。下面是Weather.java文件的代码,它有两个简单的属性icon和title,一个普通的构造函数用于初始化属性。

二、项目程序开发

  为了方便大家理解,我将程序结构流程画出来:

            图3.  重要对象关系结构

 Weather.java文件:
public class Weather {
public int icon;
public String title;
public Weather(){
super();
} public Weather(int icon, String title) {
super();
this.icon = icon;
this.title = title;
}
}

  注意,上面listview_item_row.xml文件有两个View,对应于Weather类的两个属性。Weather类的属性值将被显示到这两个View中。为了将这两个View连接起来,你需要创建一个定制的ArrayAdapter,它继承了Android的ArrayAdapter类,并重写了getView方法。添加一个新的java类到你的工程中,命名为WeatherAdapter,具体的实现代码如下:

 WeatherAdapter.java文件:
public class WeatherAdapter extends ArrayAdapter<Weather>{ Context context;
int layoutResourceId;
Weather data[] = null; public WeatherAdapter(Context context, int layoutResourceId, Weather[] data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WeatherHolder holder = null; if(row == null)
{
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false); holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle); row.setTag(holder);
}
else
{
holder = (WeatherHolder)row.getTag();
} Weather weather = data[position];
holder.txtTitle.setText(weather.title);
holder.imgIcon.setImageResource(weather.icon); return row;
} static class WeatherHolder
{
ImageView imgIcon;
TextView txtTitle;
}
}

  在上面的代码中,第一个比较重要的是类的构造函数有三个参数,第一个参数是Context对象(我们可以传递当前使用WeatherAdapter类的activity对象的引用,即MainActivity.this对象);第二个参数是resource的id(它是我们想用来呈现每个ListView的item的布局文件的id),在本文中我将传递我创建的listview_item_row.xml布局文件的id;第三个参数是一个Weather对象的数组,用于为Adapter适配器提供显示数据的数据源。

  ArrayAdapter的getView方法被重写了。这个方法将被ListView每个 item项调用来创建视图View,它们的属性是我们设置的。getView方法也使用了一个临时的holder类(在WeatherAdapter类内部声明的内部类),这个类将被用于缓存ImageView和TextView,以便它们能够被ListView中的每行重用,这也会为我们带来巨大的性能的提升,由于我们不断地访问两个相同的views(ImageView和TextView)的属性,我们不必为每个ListView的Item查找这两个控件。上面的代码也是用了Android内置的LayoutInflator来解析xml布局文件(用于动态加载xml布局文件,以便能够查找其中的内容)。

  最后一点代码是我们应用的MainActivity。里面,我们使用了所有上面声明的对象。下面是MainActivity.java文件的代码:

 MainActivity.java文件:
public class MainActivity extends Activity { private ListView listView1; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); Weather weather_data[] = new Weather[]
{
new Weather(R.drawable.weather_cloudy, "Cloudy"),
new Weather(R.drawable.weather_showers, "Showers"),
new Weather(R.drawable.weather_snow, "Snow"),
new Weather(R.drawable.weather_storm, "Storm"),
new Weather(R.drawable.weather_sunny, "Sunny")
}; WeatherAdapter adapter = new WeatherAdapter(this,
R.layout.listview_item_row, weather_data); listView1 = (ListView)findViewById(R.id.listView1); View header = (View)getLayoutInflater().inflate(R.layout.listview_header_row, null);
listView1.addHeaderView(header); listView1.setAdapter(adapter);
}

  MainActivity.java文件中有几个需要解释下的地方,以便你能更好的理解。首先,我们创建了一个Weather对象的数组,icon和title被作为参数传递给了它的构造函数;接下来,WeatherAdapter对象被创建,listview_item_row.xml文件的id和Weather对象数组被传递给了它的构造函数。再一次,我们使用了Android的LayoutInflator来解析listview_item_row.xml布局文件。通过ListView的addHeaderView方法设置ListView的header信息。最后,我们传递定制的Adapter给ListView的setAdapter方法。到现在就可以构建、运行工程了。如果一切实现正确,你会看到下面的内容。

      图2. 运行效果

  最近有一段时间没写东西了,真是罪过啊!翻译之中有不当之处在所难免,大家相互学习。尊重原创,尊重知识,相信分享的力量!

使用定制的ArrayAdapter制作ListView的Items(翻译)的更多相关文章

  1. Windows 7 封装篇(一)【母盘定制】[手动制作]定制合适的系统母盘

    Windows 7 封装篇(一)[母盘定制][手动制作]定制合适的系统母盘 http://www.win10u.com/article/html/10.html Windows 7 封装篇(一)[母盘 ...

  2. Android开发(十五)——ListView中Items的间距margin

    ListView中Items没有margin 参考:http://www.cnblogs.com/xitang/p/3677528.html

  3. ArrayAdapter和ListView

    利用ArrayAdapter向ListView中添加数据 <?xml version="1.0" encoding="utf-8"?> <Li ...

  4. BaseAdapter&ArrayAdapter在ListView中应用

    一:BaseAdapter:共同实现的基类的适配器,是ArrayAdapter SimpleAdapter等的父类, 一般用于比较复杂的ListView,扩展性强. 详细信息可查看谷歌官方API:ht ...

  5. 第二章实例:ArrayAdapter结合ListView列表视图

    package mydefault.packge; import com.example.codeview.R; import android.app.Activity; import android ...

  6. 定制应用Repeater 、ListView的模版

    若干年前有个需求:客户可在管理后台给每个新闻内容栏目指定新闻的显示样式,有的可以显示新闻时间,有的则不需要.于是就有了动态模版的应用.记得当时是用 LoadControl 的方式然后 Controls ...

  7. ListView与ArrayAdapter的搭配使用

    在android中,ListView是一种很重要的控件,一般的使用中,常建立一个所需类型的ArrayList,再通过ArrayAdapter把ListView绑定到ArrayList上,通过Array ...

  8. Android ListView ArrayAdapter 的简单使用

    前面写了3篇关于android的文章,其中的演示程序都写在了一个工程中,当时为了方便测试就在启动页MainActivity中放了3个按钮,点击不同的按钮进入不同的示例程序页面,MainActivity ...

  9. ArrayAdapter

    Android Adapter:ArrayAdapter篇 版权声明:本文为博主原创文章,未经博主允许不得转载.微博:厉圣杰源码:AndroidDemo/Notification文中如有纰漏,欢迎大家 ...

随机推荐

  1. Ios17个常用代码整理

    .判断邮箱格式是否正确的代码 //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @" ...

  2. SQL基础--&gt; 约束(CONSTRAINT)

    --============================= --SQL基础--> 约束(CONSTRAINT) --============================= 一.几类数据完 ...

  3. 经典算法:快排的Javascript版本

    function swap(arr,l,r){ var temp=arr[l]; arr[l]=arr[r]; arr[r]=temp; } function partition(arr,camp,l ...

  4. JAVA - 回调机制

    参考例子:android的Button OnClickListener接口.<第一行代码>中的回调例子   定义接口 public interface HttpCallbackListen ...

  5. Linux 字符集

    摘抄自网络--/etc/sysconfig/i18n 文件:LANG="zh_CN.GB18030"SUPPORTED="zh_CN.GB18030:zh_CN:zh:e ...

  6. grunt -- javascript自动化工具

    grunt 是一个基于npm,node.js 用js编写的工具框架,可以自动完成一些重复性的任务(如合并文件,语法检查,压缩代码), grunt拥有庞大的插件库,可以满足各种自动化批处理需求,常用的插 ...

  7. ORACLE输出详细错误信息错误行数

    ... COMMIT; --输出成功信息 DBMS_OUTPUT.PUT_LINE('RUN RESULT: SUCCESS'); EXCEPTION WHEN OTHERS THEN BEGIN R ...

  8. Lesson 6: Exploring the World of Typefaces

    Lesson 6: Exploring the World of Typefaces 这课提到的字体都是 英文 的. Article 1: More Google Web Fonts That Don ...

  9. BetWeen和模糊查询

    --区分大小写性能比较低select * from Students where Age >1 and Age <4select * from Students where Age bet ...

  10. 开发中遇到的java小知识

    今天在优化一个功能的时候遇到了instr与substr函数,之前没有接触过这两个函数,但是今天无意中用到,一查才发现,真是实用的一对兄弟啊. 先来说说substr函数,这个函数返回的是字符串的一部分. ...