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 adapter = new ArrayAdapter(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 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版)》

更多相关文章

  1. Android(安卓)Kotlin项目集成阿里ARouter
  2. Android:保存图片到Sqlite数据库
  3. Android官方提供的支持不同屏幕大小的全部方法
  4. 关于 Android(安卓)下的自动化测试方法介绍
  5. shareSdk错误码对照表
  6. Android(安卓)Retrofit + RxJava使用详解
  7. Android(安卓)之 下拉(Spinner) 组件示例
  8. 《Android》Lesson11-UI布局
  9. Android解决UnsupportedOperationException异常!

随机推荐

  1. MVC架构设计与三层模型 & MVP思想精髓与
  2. Android:(8)GridView与ImageView
  3. Android(安卓)Kotlin使用指南
  4. Android(安卓)Studio中获取sha1证书指纹
  5. Android系统与安全
  6. Unity3D for Android(安卓)纹理压缩支持
  7. Android调用堆栈跟踪
  8. [置顶] Android原生(Native)C(JNI/NDK)开
  9. Android中SoundPool 类使用利弊
  10. Android国际化快捷设置