2016/4/5 17:22】



之前写listview其实写了很多次,但好像还是模模糊糊的感觉,直到今天准备写tab的时候被告诉说原理有像的地方,于是我就先来分析整理一下listview好了



 



先来一种非常自然的理解方式:



ListView其实就是一个View中放入数据呗,于是它的使用原理很可能是这样:




android list 插入某个位置_移动开发


很好理解:


  1. 先得到数据
  2. 然后得到layout中的listview对象
  3. 然后把数据输入到对象中

 


但其实这里稍微有个实际的问题,就是第三步中,数据是不能直接传入listview中的


这也很好理解,因为


  1. 数据可能有很多种,各种各样的,肯定需要一种固定格式的数据才行,所以普通数据到这种特殊的固定格式,就需要适配器了
  2. Listview展示的不止是数据,一条条的List还有布局呢,所以你还需要传入一个布局文件

 


于是安卓中通过一个通用的适配器类(可以通过它来定制自己的)来实现这两个功能


 


这一步的变化就像这样:


    to


 


所以实际的原理示意图会是这样:


 

android list 插入某个位置_数据_02


 



而更加实际的应用中是这样:


 


1、定义一个data类


就是一个data unit,可以定义成bean的形式


但之后真正传给adapter的其实是data list,传入一个List,然后到时候listview显示的顺序就是往List添加dataitem的顺序


代码:


public   class   Zchooseproject {
  
          private   String   name 
  ;
  
          private   String   place 
  ;
  
          private   int   imageId   ;
  
       
  
          //这是从外面传入数据的方法
  
          public   Zchooseproject(String   name 
  ,String 
  place 
  , 
  int   imageId   ) {
  
                 this   .   name 
  = 
  name 
  ;
  
                 this   .   place 
  = 
  place 
  ;
  
                 this   .   imageId 
  = 
  imageId 
  ;
  
       }
  
          //这两个是在外面取数据的方法
  
          public   String getName() {
  
                 return   name   ;
  
       }
  
          public   String getPlace() {
  
                 return   place   ;
  
       }
  
          public   int   getImageId() {
  
                 return   imageId   ;
  
       }
  
              
  
}
  

     
 
  
   2、写一个itemlayout  
  

   就是普通的Layout,但是它高度是固定的,不能是matchparent(下面的例子里这块搞得有点怪,因为里边使用了wrap_content) 
 
    

   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 
  

     android:layout_width="match_parent" 
 
  

     android:layout_height="match_parent" > 
 
  

   <ImageView 
 
  

   android:id="@+id/fruit_image" 
 
  

   android:layout_width="wrap_content" 
 
  

   android:layout_height="wrap_content" /> 
 
  

   <TextView 
 
  

   android:id="@+id/fruit_name" 
 
  

   android:layout_width="wrap_content" 
 
  

   android:layout_height="wrap_content" 
 
  

   android:layout_gravity="center" 
 
  

   android:layout_marginLeft="10dip" /> 
 
  

   </LinearLayout> 
 
  

     
 
  
   3、接下来需要创建一个自定义的适配器  
  

   这个适配器继承自 ArrayAdapter(是官方适配器的一种),并将泛型指定 为我们的data类。 
 
  
1. Adapter重写了父类的一组构造函数,用于将上下文、ListView子项布局的 id和数 据都传递进来
2. 另外又重写了 getView()方法,这个方法在每个子项被滚动到屏幕内的时候 会被调用    
1. 在 getView方法中,首先通过 getItem()方法得到当前项的 Fruit实例(这个有点怪,不过没事)
2. 然后使用 LayoutInflater来为这个子项加载我们传入的布局
3. 接着调用 View的 findViewById()方法分别 获取到 ImageView和 TextView的实例,并分别调用它们的 setImageResource()和 setText()方 法来设置显示的图片和文字
4. 最后将布局返回,这样我们自定义的适配器就完成了。

     
 
  

   代码如下所示: 
 
  
      public   class   Zchooseprojectadapter   extends   ArrayAdapter<Zchooseproject> {
  
                 private   int   resourceId   ;
  
                 public   Zchooseprojectadapter(Context   context 
  , 
  int   textViewResourceId   ,List<Zchooseproject> 
  objects 
  ) {
  
                        super   (   context 
  , 
  textViewResourceId 
  , 
  objects 
  );
  
                        resourceId   = 
  textViewResourceId 
  ;
  
              }
  
                 @Override
  
                 public   View getView(   int   position   , View 
  convertView 
  , ViewGroup 
  parent 
  ) {
  

     
 
  
                     Zchooseproject   fruit   = getItem( 
  position 
  ); 
  // 获取当前项的Fruit实例
  

     
 
  
                     View   view   = LayoutInflater.from(getContext()).inflate(   resourceId   , 
  null   );
  
                     
  
                     ImageView   fruitImage   = (ImageView) 
  view 
  .findViewById(R.id. 
  fruit_image   );//获取itemlayout中的控件
  
                     TextView   fruitName   = (TextView) 
  view 
  .findViewById(R.id. 
  fruit_name   );
  
                     TextView   fruitName2   = (TextView) 
  view 
  .findViewById(R.id. 
  place   );
  

     
 
  
                        fruitImage   .setImageResource( 
  fruit 
  .getImageId());
  
                        fruitName   .setText( 
  fruit 
  .getName());
  
                        fruitName2   .setText( 
  fruit 
  .getPlace());
  
                     
  
                        return   view   ;
  
              }
  
     }
  

     
 
  
   4、OK,在onCreate方法中装配adapter吧!  
  

   4.1、初始化data list 
 
  
                private   List<Zchooseproject>   fruitList 
  = 
  new   ArrayList<Zchooseproject>();
  

     
 
  
              Zchooseproject   apple   = 
  new   Zchooseproject(   "项目名称" 
  , 
  "项目地点      项目信息" 
  , R.drawable. 
  icon_project   );
  
                 fruitList   .add( 
  apple 
  );
  
              Zchooseproject   banana   = 
  new   Zchooseproject(   "项目名称" 
  , 
  "项目地点      项目信息" 
  , R.drawable. 
  icon_project   );
  
                 fruitList   .add( 
  banana 
  );
  
              Zchooseproject   orange   = 
  new   Zchooseproject(   "项目名称" 
  , 
  "项目地点      项目信息" 
  , R.drawable. 
  icon_project   );
  
                 fruitList   .add( 
  orange 
  );
  

                            ...... 
 
  
              Zchooseproject   mango   = 
  new   Zchooseproject(   "项目名称" 
  , 
  "项目地点      项目信息" 
  , R.drawable. 
  icon_project   );
  
                 fruitList   .add( 
  mango 
  );
  

   4.2、装配adapter 
 
  
              Zchooseprojectadapter   adapter   = 
  new   Zchooseprojectadapter(   this   ,R.layout.   z_chooseprojectitem   ,   fruitList 
  );
  

     
 
  
   5、结束!装配ListView  
  
              ListView   listView   = (ListView) findViewById(R.id. 
  list_view   );
  
                 listView   .setAdapter( 
  adapter 
  );


 


因为贴图的繁琐。。。所以以上图片不完整。。。完整的在这里: