android菜鸟学习笔记14----Android控件(三) ListView的简单使用
MVC模式:
MVC的基本原理就是通过Controller连接View和Model。当View中所显示的数据发生变化时,会通知Controller,然后由Controller调用Model中的相关方法执行相应的数据修改操作。反之,当Model中的数据发生变化时,也会通知Controller,由Controller通知View更新显示内容。如此一来,就使得数据部分与视图部分相分离,任何一方发生改变都不会影响到另一方。
而在android中,MVC的一个常见应用就是ListView显示数据。V代表的就是显示控件;M代表的是各种数据源,可以是自己定义的List或者数组,也可以是数据库,文件等;C代表的是Adapter类,android中比较常见的adapter有:BaseAdapter,ArrayAdapter,SimpleAdapter等。
ListView通过setAdapter方法实现了其和一个Adapter对象的绑定,Adapter一般通过getView()方法返回当前列表项所要显示的View对象,完成了对Model中数据的读取。
当Model发生变化时,会调用BaseAdapter.notifyDataSetChanged()方法通知组件数据已然变化,此时Adapter就会调用getView()方法重新显示组件内容。
ListView:间接继承自抽象类AdapterView。
常见方法:
void setOnItemClickListener(AdapterView.OnItemClickListener listener)
void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener)
void setAdapter(ListAdapter adapter)
Adapter:是一个接口
主要的方法:
abstract int getCount() 返回要显示的item总数
abstract Object getItem(int position) 根据item索引返回该item
abstract long getItemId(int position) 返回item的id。
abstract View getView(int position, View convertView, ViewGroup parent)返回一个用来展示数据源中索引为position的View对象。
BaseAdapter是一个间接实现了Adapter接口的抽象类
自定义Adapter继承BaseAdapter时,需要提供上面四个方法的实现。主要要实现的是getCount()和geView()方法。
ArrayAdapter<T>, CursorAdapter, SimpleAdapter则直接继承自BaseAdapter,实现了其抽象方法。
ListView示例1:展示一个字符串数组中的各个字符串。
main_layout.xml:
<?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/listview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
MainActivity.java:
public class MainActivity extends Activity {
private String[] strs;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"};
ListView lv = (ListView) findViewById(R.id.listview);
lv.setAdapter(new MyBaseAdapter());
}
class MyBaseAdapter extends BaseAdapter{
@Override
public int getCount() {
return strs.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = null;
tv = new TextView(MainActivity.this);
Log.i("listview", position+"get view");
tv.setText(strs[position]);
tv.setTextSize(40);
tv.setTextColor(Color.RED);
return tv;
}
}
}
运行结果:

注意到,每次滚动屏幕显示新的item,或将滚出屏幕上方的item重新显示出来都会调用getItem()方法。而上面的代码中每次都会新建一个TextView,这样做是存在问题的。
getView(int position, View convertView, ViewGroup parent),其中参数convertView在允许的情况下,会保存旧的View实例,以便拿来复用。所以,可以利用该参数来优化上面的getView()实现。
代码修改如下:
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = null;
Log.i("listview", position+"get view");
if(convertView == null){
10
11 tv = new TextView(MainActivity.this);
12
13 }
14
15 else{
16
17 tv = (TextView) convertView;
18
19 }
tv.setText(strs[position]);
tv.setTextSize(40);
tv.setTextColor(Color.RED);
return tv;
}
其实,若只是显示数组中的内容,直接使用ArrayAdapter会比较方便:
MainActivity.java修改如下:
private String[] strs;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"};
ListView lv = (ListView) findViewById(R.id.listview);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strs);
18
19 lv.setAdapter(adapter);
}
运行结果:

其中android.R.layout.simple_list_item_1是系统自带的一个布局id。
一般来说,在ListView中显示的东西可能更加复杂点,只靠一个TextView肯定解决不了,这时,就可以为ListView中的item根据需要编写一个布局文件。
如:item_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/hero"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="35sp"
/>
</LinearLayout>
用于在线性布局中水平显示一个图片和一个字符串。
修改MyAdapter内部类的getView():
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
Log.i("listview", position+"get view");
if(convertView == null){
view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_layout, null);
}
else{
view = convertView;
}
TextView tv = (TextView) view.findViewById(R.id.tv_name);
tv.setText(strs[position]);
return view;
}
运行结果:

另一种可能常用的Adapter是SimpleAdapter。
构造函数:SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
context指定上下文
data指定存放数据的list对象,list中存放的是Map对象。
resource指定item的布局文件id
from和to是有序的,两者中的元素必须一一对应,from中存放的是list中每个map对象中的key值,to存放的是显示对应key获取的值的控件的id。
如:item_layout.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="35sp"
/>
</LinearLayout>
MainActivity.java中修改如下:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
ListView lv = (ListView) findViewById(R.id.listview);
List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
Map<String,Object> map = new HashMap<String, Object>();
map.put("img", R.drawable.hero);
map.put("str", "aaa");
data.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.hero);
map.put("str", "bbb");
data.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.hero);
map.put("str", "ccc");
data.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.hero);
map.put("str", "ddd");
data.add(map);
map = new HashMap<String, Object>();
map.put("img", R.drawable.hero);
map.put("str", "eee");
data.add(map);
SimpleAdapter sa = new SimpleAdapter(this, data, R.layout.item_layout, new String[]{"img","str"}, new int[]{R.id.iv,R.id.tv_name});
lv.setAdapter(sa);
}
显示结果:

关于ListView的事件监听:
AdapterView中定义了几个设置事件监听的方法,如:
void setOnItemClickListener(AdapterView.OnItemClickListener listener)
void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener)
ListView间接继承了AdapterView,所以,要处理事件监听时,可以调用ListView中相关的方法。
注:如果调用了ListView的setOnClickListener()方法,会报如下错误:
java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead
setOnItemClickListener()方法示例:
ListView lv = (ListView) findViewById(R.id.listview);
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Log.i("listview","onClick");
Log.i("listview",view.toString());
Log.i("listview",position+"");
Log.i("listview",id+"");
TextView tv = (TextView) view.findViewById(R.id.tv_name);
Toast.makeText(MainActivity.this, tv.getText(), Toast.LENGTH_LONG).show();
}
});
运行结果:


ListView先学到这,等学了数据库操作,也许会用到CursorAdapter等,用到时再学。
android菜鸟学习笔记14----Android控件(三) ListView的简单使用的更多相关文章
- Android开发学习笔记-自定义组合控件的过程
自定义组合控件的过程 1.自定义一个View 一般来说,继承相对布局,或者线性布局 ViewGroup:2.实现父类的构造方法.一般来说,需要在构造方法里初始化自定义的布局文件:3.根据一些需要或者需 ...
- Android开发学习笔记-自定义组合控件
为了能让代码能够更多的复用,故使用组合控件.下面是我正在写的项目中用到的方法. 1.先写要组合的一些需要的控件,将其封装到一个布局xml布局文件中. <?xml version="1. ...
- WPF-学习笔记 动态修改控件Margin的值
原文:WPF-学习笔记 动态修改控件Margin的值 举例说明:动态添加一个TextBox到Grid中,并设置它的Margin: TextBox text = new TextBox(); t_gri ...
- android菜鸟学习笔记13----Android控件(二) 自定义控件简单示例
有时候,可能觉得系统提供的控件太丑,就会需要自定义控件来实现自己想要的效果. 以下主要参考<第一行代码> 1.自定义一个标题栏: 系统自带的标题栏很丑,且没什么大的作用,所以我们之前会在o ...
- android菜鸟学习笔记12----Android控件(一) 几个常用的简单控件
主要参考<第一行代码> 1.TextView: 功能与传统的桌面应用开发中的Label控件相似,用于显示文本信息 如: <TextView android:layout_width= ...
- Android学习笔记_30_常用控件使用
一.状态栏通知(Notification): 如果需要查看消息,可以拖动状态栏到屏幕下方即可查看消息.发送消息的代码如下: public void sendNotice(View v){ int ic ...
- android 学习笔记四:控件
1.android:gravity 指定控件的基本位置,比如居中.居右等位置 Top:顶部 bottom:底部 left:居左 right:居右 center_vertical:垂直居中 center ...
- android菜鸟学习笔记7----android布局(二)
3.FrameLayout:帧布局 如同Flash或者photoshop中图层的概念,在上面的图层遮盖下面的图层,没被遮到的地方仍然显示出来. 右击res/layout,然后在弹出的菜单中选择new, ...
- android菜鸟学习笔记30----Android使用百度地图API(一)准备工作及在应用中显示地图
1.准备工作: 百度地图API是免费开放的,但是需要申请API Key: 1)先注册一个百度开发者帐号 2)进入百度开放服务平台http://developer.baidu.com/ 3)进入LBS云 ...
随机推荐
- Oracle 时间字符 转
http://www.cnblogs.com/linximf/archive/2011/11/21/2257036.html oracle数据类型看起来非常简单,但用起来会发现有许多知识点,本文是我对 ...
- Wannafly交流赛1 B 硬币[数学思维/贪心]
链接:https://www.nowcoder.com/acm/contest/69/B来源:牛客网 蜥蜴的生日快到了,就在这个月底! 今年,蜥蜴的快乐伙伴之一壁虎想要送好多个1元硬币来恶整蜥蜴. 壁 ...
- BeanFactory和ApplicationContext的异同
相同: Spring提供了两种不同的IOC 容器,一个是BeanFactory,另外一个是ApplicationContext,它们都是Java interface,ApplicationContex ...
- 快速建立ssh互信(转)
转自:魏巍的Linux酒吧 - 51CTO技术博客(http://weiweilinux.blog.51cto.com/3349074/1048212) 快速建立ssh互信 因为工作中经常需要配置服务 ...
- CoreData: 如何预载/导入已有的数据
原文地址:CoreData: 如何预载/导入已有的数据作者:出其东门 在系列教程一中,我们为对象建立了可视化数据模型,运行了快速肮脏测试并勾在一个表视图(table view)中来显示.而在这个教程, ...
- [CentOS]怎样解决gcc版本号冲突?
今天碰到一个比較坑爹的问题.在centos上用yum安装编译环境,执行: yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel o ...
- ASP.NET Web API是如何根据请求选择Action的?[下篇] 【转】
再<上篇>中我们简单介绍了用于实现Action选择机制的HttpActionSelector,接下来我们来讨论本章最为核心的内 容:ASP.NET Web API如何利用HttpActio ...
- Spark Streaming的样本demo统计
废话不多说,直接上代码 package com.demo; import java.util.List; import java.util.regex.Pattern; import org.apac ...
- Android--数据库数据显示至屏幕
MainActivity.java 这段代码的作用是从数据库中获取到数据并显示在界面上 import java.util.ArrayList; import java.util.List; impor ...
- Hibernate学习一----------Hibernate初实现
© 版权声明:本文为博主原创文章,转载请注明出处 ORM(Object/Relationship Mapping):对象/关系映射 - 利用面向对象思想编写的数据库应用程序最终都是把对象信息保存在关系 ...