天气相关信息是通过列表方式呈现的。Android SDK
提供的ListView
控件就能实现这样功能。
ListView
需要和Adapter
配合使用,ListView
负责内容的显示,Adapter
负责为ListView
提供要展示的数据。
要实现我们希望的展示效果,需要开发者自定义一个Adapter
。那我们先看看ListView
是怎么使用的。
先在我们的工程项目中使用ListView
展示一些简单的内容,大家熟悉熟悉使用ListView
的套路,
在activity_main.xml
布局文件中,给ListView
布局增加一个id
叫做weather_index_info_list
;
<ListView
android:id="@+id/weather_index_info_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
ListView>
在MainActivity.java
的源码文件里,在界面创建的时候(onCreate()当中),通过代码获取ListView
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("TEST", "Weather app launched");
ListView lv = (ListView) findViewById(R.id.weather_index_info_list);
}
java
源码通过R.id.weather_index_info_list
,将布局文件中的ListView
找了出来,转换成了可以通过java
代码操作的对象。
创建一个Adapter
负责为ListView
提供数据。Android SDK提供了很多现成的Adapter
-ArrayAdapter
CursorAdapter
SimpleAdapter
等等,不过现在我们不需要去知道每个的用法,只要知道它们都是BaseAdapter
的子类就行。它们的存在大大的简化了Adapter
的使用。
这里我先选择ArrayAdapter
,来展示下它的用法。将要显示的数据和显示这项数据项的布局设置给Adapter
,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
//每一项要显示的数据是一个字符串,这里设置显示3项
String data[] = {"a", "b", "c"};
//指定显示的数据内容,以及显示每项内容的布局文件
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
}
Android SDK提供了一些常用的数据项布局方式android.R.layout.simple_list_item_1
android.R.layout.simple_list_item_2
等等。我们也可以自己设计每一项的布局方式。
将Adapter
设置给ListView
,数据将以列表的形式被展示,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
lv.setAdapter(adapter);
}
为显示的每个item添加,点击时代响应处理函数;
@Override
protected void onCreate(Bundle savedInstanceState) {
......
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//添加需要响应的操作
}
});
}
综合以上的代码,就是,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
ListView lv = (ListView) findViewById(R.id.weather_index_info_list);
String data[] = {"a", "b", "c"};
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//添加需要响应的操作
}
});
}
最后的界面效果就是这样,
运行以后,就能看到a b c
以列表的形式,在界面上展现出来了。
如果需要展示的数据有变化,就需要更新ListView
。
ListView
的更新需要在主线程进行(UI线程)。如果在其他线程更新,系统就会报错,程序崩溃,并提示你不能在非UI线程更新界面元素
。
所以修改了Adapter
中要展示的数据后,需要使用Adapter
的notifyDataSetChanged()
通知主线程自动刷新界面;
例如,
//要显示的数据用链表的形式保存;
List data = new ArrayList();
data.add("a");
data.add("b");
data.add("c");
//指定显示的数据内容,以及显示每项内容的布局文件
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
......
//主线程中修改显示的数据项
data.add("d");
//并使用notifyDataSetChanged()刷新界面
ArrayAdapter.notifyDataSetChanged();
虽然Android SDK
为我们提供了好几种现成的Adapter使用,但有时它们也并不能完全符合我们的要求,比如满足我们希望的天气信息项界面。
因此,我们准备自定义一个Adapter。
其实SimpleAdapter
是可以满足要求的,但是为了下一阶段能容易的使用Material Design
推荐的列表控件,我就先讲一讲如何自定义Adapter,降低后面的学习难度。
为了让列表的数据项按照我们设计的模样显示,我们需要为它设计一个布局,把天气相关的指数信息展示上去。
数据项的布局定义在res\layout\weather_index_info_item_layout.xml
文件中(如何创建这种布局文件,前面已经介绍过了)。
数据项布局的方案如下,
元素 | 控件 | 属性 | id名称 |
---|---|---|---|
指数图标 | ImageView | 左边距 16dp 内容居中 | weather_index_info_icon |
指数名称 | TextView | 左边距 72dp 内容垂直居中 | weather_index_info_name |
指数取值 | TextView | 有边距 16dp 内容垂直居中 | weather_index_info_value |
数据项的整体布局 | FrameLayout | 高度48dp | 无 |
* 数据项是一个FrameLayout
,放到这个布局中的所有元素就像千层饼一样,都是一层一层堆叠起来的;
![framelayout_principle-wc300](media/framelayout_principle.png)
高度是设计规范中定义的`48dp`,
```xml
```
指数图标使用ImageView
控件,给它的android:scaleType
属性设置center
,让缩略图垂直居中放置,图片预设成ic_air_quality
;左边距是16dp
;
<ImageView
android:id="@+id/weather_index_info_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_air_quality"
android:scaleType="center"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
指数名称使用TextView
控件,它的左边距是72dp
,垂直居中放置,字体的大小和颜色按照设计的规范来指定,
<TextView
android:id="@+id/weather_index_info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="湿度"
android:layout_marginLeft="72dp"
android:layout_gravity="center_vertical"
android:textSize="16sp"
android:textColor= "#DE000000"/>
指数取值使用TextView
控件,它的右边距是16dp
,垂直居中、整体靠右放置-center_vertical|right
,字体的大小和颜色按照设计的规范来指定,
<TextView
android:id="@+id/weather_index_info_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30%"
android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|right"
android:textSize="14sp"
android:textColor= "#8A000000"/>
综合起来,如下面的布局源码,
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="48dp">
<ImageView
android:id="@+id/weather_index_info_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_air_quality"
android:scaleType="center"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:id="@+id/weather_index_info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="湿度"
android:layout_marginLeft="72dp"
android:layout_gravity="center_vertical"
android:textSize="16sp"
android:textColor= "#DE000000" />
<TextView
android:id="@+id/weather_index_info_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30%"
android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|right"
android:textSize="14sp"
android:textColor= "#8A000000"/>
FrameLayout>
最后效果图:
实现同一个布局效果的方案可以有很多种。有的方案在代码上很容易实现,有的方案可能还会考虑到布局刷新的效率。随着开发经验的增多,对各种布局实现原理的深入理解,大家会进一步的加深对布局的认识。
为了提供显示的数据内容,要先定义一个存放数据的数据结构-WeatherIndexInfo
。
首先要重新创建一个java源文件
,定义数据结构的类,
给类命名WeatherIndexInfo
,
在java
目录对应的包目录下,就生成了WeatherIndexInfo.java
文件。
我们要在这个类里面存放3个数据:图标、名称、数值。
组件名称 | 存储类型 | 说明 | 字段名称 |
---|---|---|---|
指数图标 | int | 存储图标对应的资源id |
typeResId |
指数名称 | String | 数据项的名称,描述含义 | name |
指数取值 | String | 显示名称对应的数据取值 | value |
public class WeatherIndexInfo {
public int typeResId = 0;
public String name = "";
public String value = "";
}
数据结构的定义我们暂时就到这里,这个结构在后面还会做出调整,需要和网络端的数据进行配合。我们先到此处,只要能显示列表就可以了。
现在开始自定义Adapter
-WeatherIndexInfoAdapter
。
Adapter
都是继承自BaseAdapter
的,我们这里的Adapter
准备继承自它的一个子类ArrayAdapter
。因为ArrayAdapter
在最原始的基础上作出了改进,我们再在它的基础上做一些小的调整就可以用了,而不用完全从头来过。
创建WeatherIndexInfoAdapter.java
的新类。
继承ArrayAdapter
,将显示的数据类型指定成WeatherIndexInfo
;重新构造函数,传入Context
,数据项布局使用的布局ID,要显示的数据列表;重写它的getView()
方法;
public class WeatherIndexInfoAdapter extends ArrayAdapter<WeatherIndexInfo> {
public WeatherIndexInfoAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}
在构造函数中,保存好布局ID以后使用,通过Context
获取Inflater
,为以后数据项布局的创建做准备,
private final LayoutInflater mInflater;
private final int mResource;
public WeatherIndexInfoAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
mInflater = LayoutInflater.from(context);
mResource = resource;
}
在getView()
函数中,创建数据项的布局,并为他们赋值,最后将这个布局返回给ListView
,让它显示,
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(mResource, parent, false);
}
WeatherIndexInfo item = getItem(position);
ImageView icon = (ImageView) convertView.findViewById(R.id.weather_index_info_icon);
icon.setImageResource(item.typeResId);
TextView name = (TextView) convertView.findViewById(R.id.weather_index_info_name);
name.setText(item.name);
TextView value = (TextView) convertView.findViewById(R.id.weather_index_info_value);
value.setText(item.value);
return convertView;
}
这里的convertView
就是数据项所代表的那个布局,当ListView
刚创建,还没有产生任何数据项的时候,它就是为null
的,此时我们就需要创建一个布局,并通过getView()
将这个布局返回给ListView
。
假如ListView
上的数据项布局已经足够了,那么这里传入的convertView
就不会再是null
,而是之前的某个数据项布局,我们就不必为此重新创建了,只需要更新上面的内容就好。这样提高了界面刷新的效率。
当然,这里还能通过其他方法减少使用findViewById()
,进一步提高效率,不过目前就不改进了,先把功能实现完成。
Adapter
终于完成了。
现在看看这个Adapter
怎么用。
在MainActivity
创建之时,我们在onCreate()
中创建并设置WeatherIndexInfoAdapter
,
public class MainActivity extends AppCompatActivity {
//保存ListView控件
private ListView mWeatherIndexInfoListView;
//保存天气指数信息到列表当中
private List mWeatherIndexInfoList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
mWeatherIndexInfoListView = (ListView) findViewById(R.id.weather_index_info_list);
//创建保存数据的列表,数据暂时没有
mWeatherIndexInfoList = new ArrayList<>();
//创建一个还没有添加入数据的Adapter
WeatherIndexInfoAdapter adapter = new WeatherIndexInfoAdapter(MainActivity.this, R.layout.weather_index_info_item_layout, mWeatherIndexInfoList);
mWeatherIndexInfoListView.setAdapter(adapter);
}
}
在创建Adapter
的时候,把weather_index_info_item_layout.xml
代表的布局传给了Adapter
,Adapter
将使用它来生成每个数据项的界面。
添加一些虚假的数据到Adapter
中,并使用notifyDataSetChanged()
刷新看看效果,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
WeatherIndexInfo data1 = new WeatherIndexInfo();
data1.typeResId = R.mipmap.ic_wind_level;
data1.name = "风力";
data1.value = "3级";
mWeatherIndexInfoList.add(data1);
WeatherIndexInfo data2 = new WeatherIndexInfo();
data2.typeResId = R.mipmap.ic_wind_direction;
data2.name = "风向";
data2.value = "东南";
mWeatherIndexInfoList.add(data2);
WeatherIndexInfo data3 = new WeatherIndexInfo();
data3.typeResId = R.mipmap.ic_humidity_level;
data3.name = "湿度";
data3.value = "60%";
mWeatherIndexInfoList.add(data3);
WeatherIndexInfo data4 = new WeatherIndexInfo();
data4.typeResId = R.mipmap.ic_air_quality;
data4.name = "空气质量";
data4.value = "重污染";
mWeatherIndexInfoList.add(data4);
WeatherIndexInfo data5 = new WeatherIndexInfo();
data5.typeResId = R.mipmap.ic_sport_level;
data5.name = "运动";
data5.value = "不合适";
mWeatherIndexInfoList.add(data5);
WeatherIndexInfo data6 = new WeatherIndexInfo();
data6.typeResId = R.mipmap.ic_ultraviolet_level;
data6.name = "紫外线";
data6.value = "强";
mWeatherIndexInfoList.add(data6);
adapter.notifyDataSetChanged();
}
至此,视频列表的界面就能看到视频列表了。
天气相关信息是通过列表方式呈现的。Android SDK
提供的ListView
控件就能实现这样功能。
ListView
需要和Adapter
配合使用,ListView
负责内容的显示,Adapter
负责为ListView
提供要展示的数据。
要实现我们希望的展示效果,需要开发者自定义一个Adapter
。那我们先看看ListView
是怎么使用的。
先在我们的工程项目中使用ListView
展示一些简单的内容,大家熟悉熟悉使用ListView
的套路,
在activity_main.xml
布局文件中,给ListView
布局增加一个id
叫做weather_index_info_list
;
<ListView
android:id="@+id/weather_index_info_list"
android:layout_width="match_parent"
android:layout_height="match_parent">
ListView>
在MainActivity.java
的源码文件里,在界面创建的时候(onCreate()当中),通过代码获取ListView
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("TEST", "Weather app launched");
ListView lv = (ListView) findViewById(R.id.weather_index_info_list);
}
java
源码通过R.id.weather_index_info_list
,将布局文件中的ListView
找了出来,转换成了可以通过java
代码操作的对象。
创建一个Adapter
负责为ListView
提供数据。Android SDK提供了很多现成的Adapter
-ArrayAdapter
CursorAdapter
SimpleAdapter
等等,不过现在我们不需要去知道每个的用法,只要知道它们都是BaseAdapter
的子类就行。它们的存在大大的简化了Adapter
的使用。
这里我先选择ArrayAdapter
,来展示下它的用法。将要显示的数据和显示这项数据项的布局设置给Adapter
,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
//每一项要显示的数据是一个字符串,这里设置显示3项
String data[] = {"a", "b", "c"};
//指定显示的数据内容,以及显示每项内容的布局文件
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
}
Android SDK提供了一些常用的数据项布局方式android.R.layout.simple_list_item_1
android.R.layout.simple_list_item_2
等等。我们也可以自己设计每一项的布局方式。
将Adapter
设置给ListView
,数据将以列表的形式被展示,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
lv.setAdapter(adapter);
}
为显示的每个item添加,点击时代响应处理函数;
@Override
protected void onCreate(Bundle savedInstanceState) {
......
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//添加需要响应的操作
}
});
}
综合以上的代码,就是,
@Override
protected void onCreate(Bundle savedInstanceState) {
......
ListView lv = (ListView) findViewById(R.id.weather_index_info_list);
String data[] = {"a", "b", "c"};
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
//添加需要响应的操作
}
});
}
最后的界面效果就是这样,
运行以后,就能看到a b c
以列表的形式,在界面上展现出来了。
如果需要展示的数据有变化,就需要更新ListView
。
ListView
的更新需要在主线程进行(UI线程)。如果在其他线程更新,系统就会报错,程序崩溃,并提示你不能在非UI线程更新界面元素
。
所以修改了Adapter
中要展示的数据后,需要使用Adapter
的notifyDataSetChanged()
通知主线程自动刷新界面;
例如,
//要显示的数据用链表的形式保存;
List data = new ArrayList();
data.add("a");
data.add("b");
data.add("c");
//指定显示的数据内容,以及显示每项内容的布局文件
ArrayAdapter adapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1 , data);
......
//主线程中修改显示的数据项
data.add("d");
//并使用notifyDataSetChanged()刷新界面
ArrayAdapter.notifyDataSetChanged();
虽然Android SDK
为我们提供了好几种现成的Adapter使用,但有时它们也并不能完全符合我们的要求,比如满足我们希望的天气信息项界面。
因此,我们准备自定义一个Adapter。
其实SimpleAdapter
是可以满足要求的,但是为了下一阶段能容易的使用Material Design
推荐的列表控件,我就先讲一讲如何自定义Adapter,降低后面的学习难度。
为了让列表的数据项按照我们设计的模样显示,我们需要为它设计一个布局,把天气相关的指数信息展示上去。
数据项的布局定义在res\layout\weather_index_info_item_layout.xml
文件中(如何创建这种布局文件,前面已经介绍过了)。
数据项布局的方案如下,
元素 | 控件 | 属性 | id名称 |
---|---|---|---|
指数图标 | ImageView | 左边距 16dp 内容居中 | weather_index_info_icon |
指数名称 | TextView | 左边距 72dp 内容垂直居中 | weather_index_info_name |
指数取值 | TextView | 有边距 16dp 内容垂直居中 | weather_index_info_value |
数据项的整体布局 | FrameLayout | 高度48dp | 无 |
* 数据项是一个FrameLayout
,放到这个布局中的所有元素就像千层饼一样,都是一层一层堆叠起来的;
![framelayout_principle-wc300](media/framelayout_principle.png)
高度是设计规范中定义的`48dp`,
```xml
```
指数图标使用ImageView
控件,给它的android:scaleType
属性设置center
,让缩略图垂直居中放置,图片预设成ic_air_quality
;左边距是16dp
;
<ImageView
android:id="@+id/weather_index_info_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_air_quality"
android:scaleType="center"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
指数名称使用TextView
控件,它的左边距是72dp
,垂直居中放置,字体的大小和颜色按照设计的规范来指定,
<TextView
android:id="@+id/weather_index_info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="湿度"
android:layout_marginLeft="72dp"
android:layout_gravity="center_vertical"
android:textSize="16sp"
android:textColor= "#DE000000"/>
指数取值使用TextView
控件,它的右边距是16dp
,垂直居中、整体靠右放置-center_vertical|right
,字体的大小和颜色按照设计的规范来指定,
<TextView
android:id="@+id/weather_index_info_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30%"
android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|right"
android:textSize="14sp"
android:textColor= "#8A000000"/>
综合起来,如下面的布局源码,
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="48dp">
<ImageView
android:id="@+id/weather_index_info_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_air_quality"
android:scaleType="center"
android:layout_gravity="center_vertical"
android:layout_marginLeft="16dp"/>
<TextView
android:id="@+id/weather_index_info_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="湿度"
android:layout_marginLeft="72dp"
android:layout_gravity="center_vertical"
android:textSize="16sp"
android:textColor= "#DE000000" />
<TextView
android:id="@+id/weather_index_info_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="30%"
android:layout_marginRight="16dp"
android:layout_gravity="center_vertical|right"
android:textSize="14sp"
android:textColor= "#8A000000"/>
FrameLayout>
最后效果图:
实现同一个布局效果的方案可以有很多种。有的方案在代码上很容易实现,有的方案可能还会考虑到布局刷新的效率。随着开发经验的增多,对各种布局实现原理的深入理解,大家会进一步的加深对布局的认识。
为了提供显示的数据内容,要先定义一个存放数据的数据结构-WeatherIndexInfo
。
首先要重新创建一个java源文件
,定义数据结构的类,
给类命名WeatherIndexInfo
,
在java
目录对应的包目录下,就生成了WeatherIndexInfo.java
文件。
我们要在这个类里面存放3个数据:图标、名称、数值。
组件名称 | 存储类型 | 说明 | 字段名称 |
---|---|---|---|
指数图标 | int | 存储图标对应的资源id |
typeResId |
指数名称 | String | 数据项的名称,描述含义 | name |
指数取值 | String | 显示名称对应的数据取值 | value |
public class WeatherIndexInfo {
public int typeResId = 0;
public String name = "";
public String value = "";
}
数据结构的定义我们暂时就到这里,这个结构在后面还会做出调整,需要和网络端的数据进行配合。我们先到此处,只要能显示列表就可以了。
现在开始自定义Adapter
-WeatherIndexInfoAdapter
。
Adapter
都是继承自BaseAdapter
的,我们这里的Adapter
准备继承自它的一个子类ArrayAdapter
。因为ArrayAdapter
在最原始的基础上作出了改进,我们再在它的基础上做一些小的调整就可以用了,而不用完全从头来过。
创建WeatherIndexInfoAdapter.java
的新类。
继承ArrayAdapter
,将显示的数据类型指定成WeatherIndexInfo
;重新构造函数,传入Context
,数据项布局使用的布局ID,要显示的数据列表;重写它的getView()
方法;
public class WeatherIndexInfoAdapter extends ArrayAdapter<WeatherIndexInfo> {
public WeatherIndexInfoAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
return null;
}
}
在构造函数中,保存好布局ID以后使用,通过Context
获取Inflater
,为以后数据项布局的创建做准备,
private final LayoutInflater mInflater;
private final int mResource;
public WeatherIndexInfoAdapter(Context context, int resource, List objects) {
super(context, resource, objects);
mInflater = LayoutInflater.from(context);
mResource = resource;
}
在getView()
函数中,创建数据项的布局,并为他们赋值,最后将这个布局返回给ListView
,让它显示,
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(mResource, parent, false);
}
WeatherIndexInfo item = getItem(position);
ImageView icon = (ImageView) convertView.findViewById(R.id.weather_index_info_icon);
icon.setImageResource(item.typeResId);
TextView name = (TextView) convertView.findViewById(R.id.weather_index_info_name);
name.setText(item.name);
TextView value = (TextView) convertView.findViewById(R.id.weather_index_info_value);
value.setText(item.value);
return convertView;
}
这里的convertView
就是数据项所代表的那个布局,当ListView
刚创建,还没有产生任何数据项的时候,它就是为null
的,此时我们就需要创建一个布局,并通过getView()
将这个布局返回给ListView
。
假如ListView
上的数据项布局已经足够了,那么这里传入的convertView
就不会再是null
,而是之前的某个数据项布局,我们就不必为此重新创建了,只需要更新上面的内容就好。这样提高了界面刷新的效率。
当然,这里还能通过其他方法减少使用findViewById()
,进一步提高效率,不过目前就不改进了,先把功能实现完成。
Adapter
终于完成了。
现在看看这个Adapter
怎么用。
在MainActivity
创建之时,我们在onCreate()
中创建并设置WeatherIndexInfoAdapter
,
public class MainActivity extends AppCompatActivity {
//保存ListView控件
private ListView mWeatherIndexInfoListView;
//保存天气指数信息到列表当中
private List mWeatherIndexInfoList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
mWeatherIndexInfoListView = (ListView) findViewById(R.id.weather_index_info_list);
//创建保存数据的列表,数据暂时没有
mWeatherIndexInfoList = new ArrayList<>();
//创建一个还没有添加入数据的Adapter
WeatherIndexInfoAdapter adapter = new WeatherIndexInfoAdapter(MainActivity.this, R.layout.weather_index_info_item_layout, mWeatherIndexInfoList);
mWeatherIndexInfoListView.setAdapter(adapter);
}
}
在创建Adapter
的时候,把weather_index_info_item_layout.xml
代表的布局传给了Adapter
,Adapter
将使用它来生成每个数据项的界面。
添加一些虚假的数据到Adapter
中,并使用notifyDataSetChanged()
刷新看看效果,
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
......
WeatherIndexInfo data1 = new WeatherIndexInfo();
data1.typeResId = R.mipmap.ic_wind_level;
data1.name = "风力";
data1.value = "3级";
mWeatherIndexInfoList.add(data1);
WeatherIndexInfo data2 = new WeatherIndexInfo();
data2.typeResId = R.mipmap.ic_wind_direction;
data2.name = "风向";
data2.value = "东南";
mWeatherIndexInfoList.add(data2);
WeatherIndexInfo data3 = new WeatherIndexInfo();
data3.typeResId = R.mipmap.ic_humidity_level;
data3.name = "湿度";
data3.value = "60%";
mWeatherIndexInfoList.add(data3);
WeatherIndexInfo data4 = new WeatherIndexInfo();
data4.typeResId = R.mipmap.ic_air_quality;
data4.name = "空气质量";
data4.value = "重污染";
mWeatherIndexInfoList.add(data4);
WeatherIndexInfo data5 = new WeatherIndexInfo();
data5.typeResId = R.mipmap.ic_sport_level;
data5.name = "运动";
data5.value = "不合适";
mWeatherIndexInfoList.add(data5);
WeatherIndexInfo data6 = new WeatherIndexInfo();
data6.typeResId = R.mipmap.ic_ultraviolet_level;
data6.name = "紫外线";
data6.value = "强";
mWeatherIndexInfoList.add(data6);
adapter.notifyDataSetChanged();
}
至此,视频列表的界面就能看到视频列表了。