ListView在android开放中用的比较多,所以接下来就进行ListView的使用的讲解。

首先创建一个android项目,项目名为ListViewTest.

ListView的简单使用

修改布局文件,修改后代码如下:

 

view source print ? 01. "http://schemas.android.com/apk/res/android" 02. xmlns:tools="http://schemas.android.com/tools" 03. android:layout_width="match_parent" 04. android:layout_height="match_parent" 05. > 06.   07. 08. android:id="@+id/list_view" 09. android:layout_width="match_parent" 10. android:layout_height="match_parent" 11. > 12.   13.

 

修改MainActivity的代码:

 

view source print ? 01. package com.wj.listviewtest; 02.   03. import android.app.Activity; 04. import android.os.Bundle; 05. import android.view.Menu; 06. import android.widget.ArrayAdapter; 07. import android.widget.ListView; 08.   09. public class MainActivity extends Activity { 10.   11. private String [] data={"apple","banana","orange", 12. "watermelon","pear","grape","pineapple","strawberry", 13. "cherry","mango"}; 14. @Override 15. protected void onCreate(Bundle savedInstanceState) { 16. super.onCreate(savedInstanceState); 17. setContentView(R.layout.activity_main); 18. //创建适配器 19. ArrayAdapter adapter=new ArrayAdapter( 20. MainActivity.this,android.R.layout.simple_list_item_1, 21. data); 22. ListView listView=(ListView) findViewById(R.id.list_view); 23. listView.setAdapter(adapter); 24. } 25.   26. @Override 27. public boolean onCreateOptionsMenu(Menu menu) { 28. // Inflate the menu; this adds items to the action bar if it is present. 29. getMenuInflater().inflate(R.menu.main, menu); 30. return true; 31. } 32.   33. }

 

运行程序结果如下:

ListView是用于显示大量数据的,这些数据我们可以事先准备好,也可以从网上或者数据中中读取。

android.R.layout.simple_list_item_1是作为ListView子项布局的id,这是android内置的布局文件里面只有一个TextView,可用于简单地显示一段文本。

2.定制ListView的界面

首先准备一组图片,分别对应上面提供的水果。

接着定义一个实体类,作为ListView适配器的适配类型,新建Fruit类,代码如下:

 

view source print ? 01. package com.wj.listviewtest; 02.   03. public class Fruit { 04.   05. private String name;//水果名 06. private int imageId;//水果图片的资源id 07.   08. //无参构造函数 09. public Fruit(){} 10. //有参构造函数 11. public Fruit(String name,int imageId){ 12. this.name=name; 13. this.imageId=imageId; 14. } 15.   16. public String getName() { 17. return name; 18. } 19. public void setName(String name) { 20. this.name = name; 21. } 22. public int getImageId() { 23. return imageId; 24. } 25. public void setImageId(int imageId) { 26. this.imageId = imageId; 27. } 28.   29. }
Fruit类中只有2个字段,name表示水果的名字,imageId表示水果对应图片的资源id,然后需要为ListView的子项指定一个我们自定义的布局,在layout目录下面新建fruit_item.xml代码如下:

 

 

view source print ? 01. <?xml version="1.0" encoding="utf-8"?> 02. "http://schemas.android.com/apk/res/android" 03. android:layout_width="match_parent" 04. android:layout_height="match_parent" 05. > 06. 07. android:id="@+id/fruit_image" 08. android:layout_width="wrap_content" 09. android:layout_height="wrap_content" 10. /> 11.   12. 13. android:id="@+id/fruit_name" 14. android:layout_width="wrap_content" 15. android:layout_height="wrap_content" 16. android:layout_gravity="center" 17. android:layout_marginLeft="10dip" 18. /> 19.   20.

 

这个布局中我们定义了一个ImageView用于显示水果的图片,又定义了一个TextView用于显示水果的名称。

接着我们要创建一个自定义的适配器,这个适配器继承自ArrayAdapter,并将泛型指定为Fruit。新建一个类FruitAdapter代码如下:

 

view source print ? 01. package com.wj.listviewtest; 02.   03. import java.util.List; 04.   05. import android.content.Context; 06. import android.view.LayoutInflater; 07. import android.view.View; 08. import android.view.ViewGroup; 09. import android.widget.ArrayAdapter; 10. import android.widget.ImageView; 11. import android.widget.TextView; 12.   13. public class FruitAdapter extends ArrayAdapter { 14.   15. private int resourceId; 16. public FruitAdapter(Context context, int textViewResourceId, 17. List objects) { 18. super(context, textViewResourceId, objects); 19. // TODO Auto-generated constructor stub 20. /* 21. * 重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据都传进来。 22. * */ 23. resourceId=textViewResourceId; 24. } 25. @Override 26. public View getView(int position, View convertView, ViewGroup parent) { 27. // TODO Auto-generated method stub 28. //return super.getView(position, convertView, parent); 29. /* 30. * 重写getView方法,这个方法在每个子项被滚动到屏幕内的时候会被调用,在getView方法中 31. * ,首先通过getItem方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项加载 32. * 我们传入的布局,接着调用View的findViewById方法分别获取到ImageView和TextView的实例, 33. * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字,最后返回布局 34. * */ 35. Fruit fruit=getItem(position);//获取当前项的Fruit实例 36. //初始话ListView的子项布局 37. View view=LayoutInflater.from(getContext()).inflate(resourceId, null); 38. ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image); 39. TextView fruitName=(TextView) view.findViewById(R.id.fruit_name); 40. fruitImage.setImageResource(fruit.getImageId()); 41. fruitName.setText(fruit.getName()); 42. return view; 43. } 44.   45.   46.   47.   48. }
修改MainActivity的代码如下:

 

 

view source print ? 01. package com.wj.listviewtest; 02.   03. import java.util.ArrayList; 04. import java.util.List; 05.   06. import android.app.Activity; 07. import android.os.Bundle; 08. import android.view.Menu; 09. import android.widget.ArrayAdapter; 10. import android.widget.ListView; 11.   12. public class MainActivity extends Activity { 13.   14. /*private String [] data={"apple","banana","orange", 15. "watermelon","pear","grape","pineapple","strawberry", 16. "cherry","mango"};*/ 17. private List fruitList=new ArrayList(); 18. @Override 19. protected void onCreate(Bundle savedInstanceState) { 20. super.onCreate(savedInstanceState); 21. setContentView(R.layout.activity_main); 22. /*//创建适配器 23. ArrayAdapter adapter=new ArrayAdapter( 24. MainActivity.this,android.R.layout.simple_list_item_1, 25. data); 26. ListView listView=(ListView) findViewById(R.id.list_view); 27. listView.setAdapter(adapter);*/ 28. initFruits();//初始化水果 29. FruitAdapter adapter=new FruitAdapter(MainActivity.this, 30. R.layout.fruit_item, fruitList); 31. ListView listView=(ListView) findViewById(R.id.list_view); 32. //设置适配器 33. listView.setAdapter(adapter); 34.   35. } 36.   37. @Override 38. public boolean onCreateOptionsMenu(Menu menu) { 39. // Inflate the menu; this adds items to the action bar if it is present. 40. getMenuInflater().inflate(R.menu.main, menu); 41. return true; 42. } 43.   44. public void initFruits(){ 45. Fruit apple=new Fruit("apple",R.drawable.apple_pic); 46. fruitList.add(apple); 47. Fruit banana=new Fruit("banana",R.drawable.banana_pic); 48. fruitList.add(banana); 49. Fruit orange=new Fruit("orange",R.drawable.orange_pic); 50. fruitList.add(orange); 51. Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic); 52. fruitList.add(watermelon); 53. Fruit pear=new Fruit("pear",R.drawable.pear_pic); 54. fruitList.add(pear); 55. Fruit grape=new Fruit("grape",R.drawable.grape_pic); 56. fruitList.add(grape); 57. Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic); 58. fruitList.add(pineapple); 59. Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic); 60. fruitList.add(strawberry); 61. Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic); 62. fruitList.add(cherry); 63. Fruit mango=new Fruit("mango",R.drawable.mango_pic); 64. fruitList.add(mango); 65. } 66.   67.   68.   69. }
运行程序,结果如下:

 

这是一个简单的界面,不过更加复杂的界面也可以通过修改fruit_item.xml文件来实现更加复杂的ListView。

下面我们来提示下ListView的运行效率。

目前我们的ListView的运行效率是很低的,因为在FruitAdapter的getView方法中每次都要将布局重写加载了一遍,当ListView快速滚动的时候这就会成为性能的瓶颈。仔细观察,getView方法中还有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以进行重用,修改FruitAdapter中的代码,带入如下所示:

 

view source print ? 01. @Override 02. public View getView(int position, View convertView, ViewGroup parent) { 03. // TODO Auto-generated method stub 04. //return super.getView(position, convertView, parent); 05. /* 06. * 重写getView方法,这个方法在每个子项被滚动到屏幕内的时候会被调用,在getView方法中 07. * ,首先通过getItem方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项加载 08. * 我们传入的布局,接着调用View的findViewById方法分别获取到ImageView和TextView的实例, 09. * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字,最后返回布局 10. * */ 11. Fruit fruit=getItem(position);//获取当前项的Fruit实例 12. View view; 13. /* 14. * 在getView()方法中进行判断,如果convertView为空,则使用LayoutInflater去加载布局, 15. * 如果不为空,则直接对convertView进行重用。这样可以大大提升ListView的效率,在快速滚动的时候 16. * 也可以表现更好的性能。 17. * */ 18. if(convertView==null){ 19. //初始话ListView的子项布局 20. view=LayoutInflater.from(getContext()).inflate(resourceId, null); 21. }else{ 22. view=convertView; 23. } 24. /*//初始话ListView的子项布局 25. View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/ 26. ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image); 27. TextView fruitName=(TextView) view.findViewById(R.id.fruit_name); 28. fruitImage.setImageResource(fruit.getImageId()); 29. fruitName.setText(fruit.getName()); 30. return view; 31. }
上面的代码进行了部分的优化,虽然现在已经不用在重复的去加载布局了,但是每次在getView方法中还是会调用View的view.findViewById()方法来获取一次控件的实例。我们可以借助一个ViewHolder来对这部分性能进行优化,修改FruitAdapter中的代码,如下所示:

 

 

view source print ? 01. package com.wj.listviewtest; 02.   03. import java.util.List; 04.   05. import android.content.Context; 06. import android.view.LayoutInflater; 07. import android.view.View; 08. import android.view.ViewGroup; 09. import android.widget.ArrayAdapter; 10. import android.widget.ImageView; 11. import android.widget.TextView; 12.   13. public class FruitAdapter extends ArrayAdapter { 14.   15. private int resourceId; 16. public FruitAdapter(Context context, int textViewResourceId, 17. List objects) { 18. super(context, textViewResourceId, objects); 19. // TODO Auto-generated constructor stub 20. /* 21. * 重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据都传进来。 22. * */ 23. resourceId=textViewResourceId; 24. } 25. @Override 26. public View getView(int position, View convertView, ViewGroup parent) { 27. // TODO Auto-generated method stub 28. //return super.getView(position, convertView, parent); 29. /* 30. * 重写getView方法,这个方法在每个子项被滚动到屏幕内的时候会被调用,在getView方法中 31. * ,首先通过getItem方法得到当前项的Fruit实例,然后使用LayoutInflater来为这个子项加载 32. * 我们传入的布局,接着调用View的findViewById方法分别获取到ImageView和TextView的实例, 33. * 并分别调用他们的setImageResource和setText方法来设置显示的图片和文字,最后返回布局 34. * */ 35. Fruit fruit=getItem(position);//获取当前项的Fruit实例 36. View view; 37. ViewHolder viewHolder; 38. /* 39. * 在getView()方法中进行判断,如果convertView为空,则使用LayoutInflater去加载布局, 40. * 如果不为空,则直接对convertView进行重用。这样可以大大提升ListView的效率,在快速滚动的时候 41. * 也可以表现更好的性能。 42. * */ 43. if(convertView==null){ 44. //初始话ListView的子项布局 45. view=LayoutInflater.from(getContext()).inflate(resourceId, null); 46. viewHolder=new ViewHolder(); 47. viewHolder.fruitImage=(ImageView) view.findViewById(R.id.fruit_image); 48. viewHolder.fruitName=(TextView) view.findViewById(R.id.fruit_name); 49. view.setTag(viewHolder);//将ViewHolder存储在View中 50. }else{ 51. view=convertView; 52. viewHolder=(ViewHolder) view.getTag();//重新获取ViewHolder 53. } 54. /*//初始话ListView的子项布局 55. View view=LayoutInflater.from(getContext()).inflate(resourceId, null);*/ 56. /*ImageView fruitImage=(ImageView) view.findViewById(R.id.fruit_image); 57. TextView fruitName=(TextView) view.findViewById(R.id.fruit_name);*/ 58. viewHolder.fruitImage.setImageResource(fruit.getImageId()); 59. viewHolder.fruitName.setText(fruit.getName()); 60. return view; 61. } 62.   63.   64. class ViewHolder{ 65. ImageView fruitImage; 66. TextView  fruitName; 67. } 68.   69. }
通过上面两步优化后,ListView的运行效率已经不错了。

 

ListView的点击事件

修改代码如下:

 

view source print ? 01. package com.wj.listviewtest; 02.   03. import java.util.ArrayList; 04. import java.util.List; 05.   06. import android.app.Activity; 07. import android.os.Bundle; 08. import android.view.Menu; 09. import android.view.View; 10. import android.widget.AdapterView; 11. import android.widget.AdapterView.OnItemClickListener; 12. import android.widget.ArrayAdapter; 13. import android.widget.ListView; 14. import android.widget.Toast; 15.   16. public class MainActivity extends Activity { 17.   18. /*private String [] data={"apple","banana","orange", 19. "watermelon","pear","grape","pineapple","strawberry", 20. "cherry","mango"};*/ 21. private List fruitList=new ArrayList(); 22. @Override 23. protected void onCreate(Bundle savedInstanceState) { 24. super.onCreate(savedInstanceState); 25. setContentView(R.layout.activity_main); 26. /*//创建适配器 27. ArrayAdapter adapter=new ArrayAdapter( 28. MainActivity.this,android.R.layout.simple_list_item_1, 29. data); 30. ListView listView=(ListView) findViewById(R.id.list_view); 31. listView.setAdapter(adapter);*/ 32. initFruits();//初始化水果 33. FruitAdapter adapter=new FruitAdapter(MainActivity.this, 34. R.layout.fruit_item, fruitList); 35. ListView listView=(ListView) findViewById(R.id.list_view); 36. //设置适配器 37. listView.setAdapter(adapter); 38. /* 39. * setOnItemClickListener()方法来为ListView注册一个监听器,当用户点击了ListView 40. * 中的任何一个子项时就会回调nItemClick()方法,在这个方法中可以通过position参数判断出用户点击 41. * 的是哪一个子项,然后获取相应的水果,并通过Toast将水果的名字显示出来。 42. * */ 43. listView.setOnItemClickListener(new OnItemClickListener(){ 44.   45. @Override 46. public void onItemClick(AdapterView<?> parent, View view, int position, 47. long id) { 48. // TODO Auto-generated method stub 49. Fruit fruit=fruitList.get(position); 50. Toast.makeText(MainActivity.this, 51. fruit.getName(), Toast.LENGTH_SHORT).show(); 52.   53. } 54.   55. }); 56. } 57.   58. @Override 59. public boolean onCreateOptionsMenu(Menu menu) { 60. // Inflate the menu; this adds items to the action bar if it is present. 61. getMenuInflater().inflate(R.menu.main, menu); 62. return true; 63. } 64.   65. public void initFruits(){ 66. Fruit apple=new Fruit("apple",R.drawable.apple_pic); 67. fruitList.add(apple); 68. Fruit banana=new Fruit("banana",R.drawable.banana_pic); 69. fruitList.add(banana); 70. Fruit orange=new Fruit("orange",R.drawable.orange_pic); 71. fruitList.add(orange); 72. Fruit watermelon=new Fruit("watermelon",R.drawable.watermelon_pic); 73. fruitList.add(watermelon); 74. Fruit pear=new Fruit("pear",R.drawable.pear_pic); 75. fruitList.add(pear); 76. Fruit grape=new Fruit("grape",R.drawable.grape_pic); 77. fruitList.add(grape); 78. Fruit pineapple=new Fruit("pineapple",R.drawable.pineapple_pic); 79. fruitList.add(pineapple); 80. Fruit strawberry=new Fruit("strawberry",R.drawable.strawberry_pic); 81. fruitList.add(strawberry); 82. Fruit cherry=new Fruit("cherry",R.drawable.cherry_pic); 83. fruitList.add(cherry); 84. Fruit mango=new Fruit("mango",R.drawable.mango_pic); 85. fruitList.add(mango); 86. } 87.   88.   89.   90. }

 

运行结果如下;

好了ListView的使用就总结到这里了。

单位和尺寸

px是像素的意思,即屏幕中可以显示的最小单位,我们应用里任何可见的东西都是由一个个像素点组成的。

pt是磅数的意思,1磅等于1/72英寸,一般pt都会作为字体的单位来使用。

dp是密度无关的像素的意思,也被称作为dip,和px相比,它在不同密度的屏幕中的显示比例保持一致。

sp是可伸缩像素的意思,它采用了和dp同样的设计理念,解决了文字大小的适配问题。

android中的密度就是屏幕每英寸所包含的像素数,通常以dpi为单位。

根据android的规定,在160dpi的屏幕上,1dp等于1px,而在320dpi的屏幕上,1dp就等于2px。因此,使用dp来指定控件的宽和高,就可以保证控件在不同密度的屏幕中的显示比例保存一致。所以dp可以理解为显示比例(像素除以英寸)

在编写android程序的时候,尽量将控件或布局的大小指定成match_parent或wrap_content,如果必须要指定一个固定的值,则使用dp来作为单位,指定文字的大小的时候使用sp。

更多相关文章

  1. android 异常问题解决
  2. Android(安卓)Root方法原理解析及Hook(一) adbd漏洞
  3. android:屏幕自适应
  4. Android菜鸟日记29-杂记
  5. 浅谈android系统java调用C++函数传参过程
  6. 《宅男的android开发指南》(翻译)--2
  7. Android学习笔记(九) Android文件读写操作
  8. 浅谈Java中Collections.sort对List排序的两种方法
  9. Python list sort方法的具体使用

随机推荐

  1. android media 播放器
  2. Android瀑布流的实现
  3. Android中JNI的使用之HelloWorld
  4. (连载)Android 8.0 : 系统启动流程之Linu
  5. Android开发(九)| android手势开发
  6. android:动态缩放和旋转图像
  7. Android(安卓)textview字体颜色显示和图
  8. Android中的基础----如何获得LinearLayou
  9. Android(安卓)Runnable 运行在那个线程
  10. design principle:模拟 android Button 控