Android自学——ListView
来源:互联网 发布:java怎么定义函数 编辑:程序博客网 时间:2024/06/08 16:24
ListView
简介:ListView允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,例如QQ的聊天记录等。所谓ListView也就是把具有相同布局的View给放在一个列表中展示而已。
使用ListView需要设置数据适配器Adapter,那什么是Adapter?
Adapter
An Adapter object acts as a bridge between an AdapterView and the underlying data for that view. The Adapter provides access to the data items. The Adapter is also responsible for making a View for each item in the data set.
一个Adapter是AdapterView视图与数据之间的桥梁,Adapter提供对数据的访问,也负责为每一项数据产生一个对应的View,后将View添加到ListView之中。
可能直接这样说比较抽象,下面我们来举例说明一下:我们的手机通讯录就是一个简单的ListView。通讯录中有一条一条的联系人,每一个联系人都显示了相应的信息。现在通讯录比较简单,一般情况下只显示头像和姓名,以前还会显示手机号。每一条联系人的显示方式又是一个View。Adapter适配器将我们的信息(头像和姓名)根据一定的格式适配到每个View中,然后再将View添加到ListView中。大家根据这个例子可能对ListView控件和Adapter适配器以及他们之间的关系有了更好的理解了。
引用自http://www.cnblogs.com/gaobig/p/5016651.html
Adapter的构造函数有三个参数,分别代表当前上下文
、ListView子项布局的id
和要适配的数据
。
Android提供了很多适配器的实现类,我们这里先看看ArrayAdapter,其通过泛型来指定要适配的数据,比如我们要传入文本类型的数据:
private String[] data = {"a", "b", "c", "d", "e", "f", "g"};@Overrideprotected void onCreate(Bindle savedInstanceState) { super.onCreate(saveInstanceState); setContentView(R.id.activity_main); //生成适配器实例,其中android.R.layout.simple_list_item_1是内置的简单布局,只含有一个TextView ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, data); //生成ListView实例并载入适配器, //其中R.id.lsit_view是自定义的ListView控件,该控件的用法和普通控件一样,这里就不写布局的代码了 ListView listView = (ListView) findViewById(R.id.lsit_view); listView.setAdapter(adapter);}
Adapter中有一个getView()
方法,每当子项被滚动到屏幕内的时候就会被ListView调用,用于干什么呢?当然是给当前的ListView的子项填进一个View,所以理所当然该方法返回的是View类型,因此如果要自定义ListView的子项布局的话,就可以自己新建一个View然后再用自定义的布局的控件跟View绑定到一起。
那怎么绑定呢?我们看一下下面的例子:
@Overridepublic View getView(int position, View convertView, ViewGroup parent) { View view = LayoutInflater.from(getContext()).inflate(自定义子项布局的id, parent, false); //对View中的控件进行设置,如: TextView text = (TextView) view.findViewById(R.id.text); text.setText("Hello"); return view;}
这里有必要再解释一下LayoutInflater.from(getContext()).inflate()
。
LayoutInflater.from(getContext())
可以构造出一个LayoutInflater对象,然后调用inflate()
方法动态加载一个布局。inflate()
方法有三个参数,,第一个参数是要填充的布局的id,第二个是父布局,第三个是是否把布局先添加到父布局再返回View。其中第三个参数省略的话默认为true:
inflate()
方法第三个参数attachToRoot是true的话,那第一个参数的layout文件就会被填充并附加在第二个参数所指定的ViewGroup内。方法返回结合后的View,根元素是第二个参数ViewGroup。如果是false的话,第一个参数所指定的layout文件会被填充并作为View返回。这个View的根元素就是layout文件的根元素。不管是true还是false,都需要ViewGroup的LayoutParams来正确的测量与放置layout文件所产生的View对象。作者:斯科特安链接:http://www.jianshu.com/p/41796f541e67來源:简书 著作权归作者所有。
反正就是这样来给View加载布局的。
然后就是要说说怎么自定义Adapter了,比如我们要在ListView中展示水果图片+名字的一组列表:
/*在定义Adapter之前先定义一个我们要展示的数据的类*/public class Fruit { private String name; private int imageId; public Fruit(String name, int imagId) { this.name = name; this.imageId = imageId; } //此处省略两个成员变量的getter和setter方法 ...}
/*一般自定义Adapter可以选择继承ArrayAdapter,可以省下很多功夫*/public class FruitAdapter extends ArrayAdapter<Fruit> { //resourceId是我们自定义的布局的id,在后面的getView()方法中需要用来给View加载布局 private int resourceId; //第二个参数之所以叫textViewResourceId是因为我们继承的ArrayAdapter就是只用来展示TextView的 //我们自定义的时候就可以传入我们自定义的布局id public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects) { super(context, textViewResourceId, objects); resourceId = textViewResourceId; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false); //对View中的控件进行设置 TextView fruitName = (TextView) view.findViewById(R.id.name); ImagView fruitImage = (ImageView) view.findViewById(R.id.image) //getItem()方法是继承的ArrayAdapter中实现的方法,用于获取当前项的数据的实例 Fruit fruit = getItem(position); fruitName.setText(fruit.getName()); fruitImage.setImageResource(fruit.getImageId); return view; }}
自定义Adapter就是这样子了,应该没什么问题吧, 使用的话就跟ArrayAdapter的用法类似就可以了。
下面来学习怎么优化ListView的性能。
首先由于每次子项进入怕屏幕的时候都会调用getView()
方法,这样会导致每次都重新加载布局,当ListView快速滚动的时候性能就很差。
仔细看Adapter的getView()
方法,还会发现它的第二个参数convertView我们没有用到,这个参数就是用来缓存之前加载好的布局的。所以我们修改一下上面例子中getView()
的内容:
@Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = = LayoutInflater.from(getContext()).inflate(resourceId, parent, false); } else { view = convertView; } ... }}
其次由于getView()
方法中每次都会调用findViewById()
来获取控件实例,因此我们可以借助一个ViewHolder来进行优化:
@Override public View getView(int position, View convertView, ViewGroup parent) { Fruit fruit = getItem(position); View view; ViewHolder viewHolder; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false); viewHolder = new ViewHolder(); viewHolder.image = (ImageView) view.findViewById(R.id.iamge); viewHolder.name = (TextView) view.findViewById(R.id.name); //调用View的setTag()方法,该方法可以存储和View相关联的信息,然后调用View的getTag()可以读取信息 view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder) view.getTag(); } viewHolder.name.setText(fruit.getName()); viewHolder.image.setImageResource(fruit.getImageId()); return view; }}class ViewHolder { ImageView image; TextView name;}
至此ListView的性能就很不错了。
ListView的每一个子项是可以点击的,下面学习一下如何注册点击事件。
ListView listView = (ListView) findViewById(R.id.list_View);listView.setAdapter(adapter);lsitView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Fruit fruit = fruitList.get(position); Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show(); }});
其实跟Button和TextView等的监听器差不多,过一下就可以了。
ListView的学习就到这里了,初次写博客,有啥错误欢迎批评指出。
主要参考文献:郭霖《第一行代码(第2版)》
- Android自学——ListView
- android 自学日记(五) ——ListView
- Android—开发自学历程(1)-Activity(5)-ListView
- 如何自学Android编程——Android自学资料大全
- Android自学笔记-11-listview简单例子
- android——ListView
- Android —定制ListView
- 自学android——AutoCompleteTextView的使用
- Android自学——RecyclerView初步
- 喝酒不骑马的Android自学日记(6)-ListView
- Android基础知识——ListView
- Android——ListView控件
- android控件——ListView
- Android控件——ListView
- Android API 中文 — ListView
- android控件—ListView(1)
- Android—开发自学历程(2)-Service
- Android—开发自学历程(3)-多线程
- si4438 的初始化
- JavaScript和HTML事件处理程序属性中的this的含义
- 阿里云部署redis服务器,以及远程访问
- Jlink 命令调试-断点/条件断点
- 递归倒序字符串的方法(1207)
- Android自学——ListView
- spring-xxxJar包
- Android动画之帧动画(三)
- base64加解密源码(可直接调用)
- 文章标题
- Codeforces Round #118 (Div. 2)-C-Plant(构造矩阵)
- Java入门_Java基础知识下
- 端口映射
- AR技术新突破,基于图的平面物体跟踪算法Gracker