• 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:展示一个字符串数组中的各个字符串。

     1 main_layout.xml:
     2 
     3 <?xml version="1.0" encoding="utf-8"?>
     4 
     5 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     6 
     7     android:layout_width="match_parent"
     8 
     9     android:layout_height="match_parent"
    10 
    11     android:orientation="vertical" >
    12 
    13     <ListView
    14 
    15         android:id="@+id/listview"
    16 
    17         android:layout_width="wrap_content"
    18 
    19         android:layout_height="wrap_content"
    20 
    21         />
    22 
    23 </LinearLayout>

     MainActivity.java:

     1 public class MainActivity extends Activity {
     2 
     3      
     4 
     5       private String[] strs;
     6 
     7       @Override
     8 
     9       protected void onCreate(Bundle savedInstanceState) {
    10 
    11            // TODO Auto-generated method stub
    12 
    13            super.onCreate(savedInstanceState);
    14 
    15            setContentView(R.layout.main_layout);
    16 
    17            strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"};
    18 
    19            ListView lv = (ListView) findViewById(R.id.listview);
    20 
    21            lv.setAdapter(new MyBaseAdapter());
    22 
    23           
    24 
    25       }
    26 
    27       class MyBaseAdapter extends BaseAdapter{
    28 
    29            @Override
    30 
    31            public int getCount() {
    32 
    33                  return strs.length;
    34 
    35            }
    36 
    37            @Override
    38 
    39            public Object getItem(int position) {
    40 
    41                  // TODO Auto-generated method stub
    42 
    43                  return null;
    44 
    45            }
    46 
    47            @Override
    48 
    49            public long getItemId(int position) {
    50 
    51                  return 0;
    52 
    53            }
    54 
    55            @Override
    56 
    57            public View getView(int position, View convertView, ViewGroup parent) {
    58 
    59                  TextView tv = null;
    60 
    61                  tv = new TextView(MainActivity.this);
    62 
    63                  Log.i("listview", position+"get view");
    64 
    65                  tv.setText(strs[position]);
    66 
    67                  tv.setTextSize(40);
    68 
    69                  tv.setTextColor(Color.RED);
    70 
    71                  return tv;
    72 
    73            }
    74 
    75       }
    76 
    77 }

     运行结果:

     

    注意到,每次滚动屏幕显示新的item,或将滚出屏幕上方的item重新显示出来都会调用getItem()方法。而上面的代码中每次都会新建一个TextView,这样做是存在问题的。

    getView(int position, View convertView, ViewGroup parent),其中参数convertView在允许的情况下,会保存旧的View实例,以便拿来复用。所以,可以利用该参数来优化上面的getView()实现。

    代码修改如下:

     1 public View getView(int position, View convertView, ViewGroup parent) {
     2 
     3  
     4 
     5                  TextView tv = null;
     6 
     7                  Log.i("listview", position+"get view");
     8 
     9                  if(convertView == null){
    10 
    11                       tv = new TextView(MainActivity.this);
    12 
    13                  }
    14 
    15                  else{
    16 
    17                       tv = (TextView) convertView;
    18 
    19                  }
    20 
    21                  tv.setText(strs[position]);
    22 
    23                  tv.setTextSize(40);
    24 
    25                  tv.setTextColor(Color.RED);
    26 
    27                  return tv;
    28 
    29 }

    其实,若只是显示数组中的内容,直接使用ArrayAdapter会比较方便:

    MainActivity.java修改如下:

     1 private String[] strs;
     2 
     3       @Override
     4 
     5       protected void onCreate(Bundle savedInstanceState) {
     6 
     7            // TODO Auto-generated method stub
     8 
     9            super.onCreate(savedInstanceState);
    10 
    11            setContentView(R.layout.main_layout);
    12 
    13            strs = new String[]{"aaa","bbb","ccc","ddd","eee","fff","ggg","hhh","iii"};
    14 
    15            ListView lv = (ListView) findViewById(R.id.listview);
    16 
    17            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, strs);
    18 
    19            lv.setAdapter(adapter);
    20 
    21           
    22 
    23       }

    运行结果:

     

    其中android.R.layout.simple_list_item_1是系统自带的一个布局id。

    一般来说,在ListView中显示的东西可能更加复杂点,只靠一个TextView肯定解决不了,这时,就可以为ListView中的item根据需要编写一个布局文件。

    如:item_layout.xml:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2 
     3     android:layout_width="match_parent"
     4 
     5     android:layout_height="match_parent"
     6 
     7     android:orientation="horizontal" >
     8 
     9     <ImageView
    10 
    11         android:layout_width="wrap_content"
    12 
    13         android:layout_height="wrap_content"
    14 
    15         android:src="@drawable/hero"
    16 
    17         />
    18 
    19     <TextView
    20 
    21         android:id="@+id/tv_name"
    22 
    23         android:layout_width="wrap_content"
    24 
    25         android:layout_height="wrap_content"
    26 
    27         android:textSize="35sp"
    28 
    29         />
    30 
    31 </LinearLayout>

     用于在线性布局中水平显示一个图片和一个字符串。

    修改MyAdapter内部类的getView():

     1 public View getView(int position, View convertView, ViewGroup parent) {
     2 
     3  
     4 
     5                  View view = null;
     6 
     7                  Log.i("listview", position+"get view");
     8 
     9                  if(convertView == null){
    10 
    11                       view = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_layout, null);
    12 
    13                  }
    14 
    15                  else{
    16 
    17                       view =  convertView;
    18 
    19                  }
    20 
    21                  TextView tv = (TextView) view.findViewById(R.id.tv_name);
    22 
    23                  tv.setText(strs[position]);
    24 
    25                  return view;
    26 
    27            }

     运行结果:

     

    另一种可能常用的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:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2 
     3     android:layout_width="match_parent"
     4 
     5     android:layout_height="match_parent"
     6 
     7     android:orientation="horizontal" >
     8 
     9     <ImageView
    10 
    11         android:id="@+id/iv"
    12 
    13         android:layout_width="wrap_content"
    14 
    15         android:layout_height="wrap_content"
    16 
    17         />
    18 
    19     <TextView
    20 
    21         android:id="@+id/tv_name"
    22 
    23         android:layout_width="wrap_content"
    24 
    25         android:layout_height="wrap_content"
    26 
    27         android:textSize="35sp"
    28 
    29         />
    30 
    31 </LinearLayout>

    MainActivity.java中修改如下:

     1 protected void onCreate(Bundle savedInstanceState) {
     2 
     3            // TODO Auto-generated method stub
     4 
     5            super.onCreate(savedInstanceState);
     6 
     7            setContentView(R.layout.main_layout);
     8 
     9            ListView lv = (ListView) findViewById(R.id.listview);
    10 
    11            List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
    12 
    13            Map<String,Object> map = new HashMap<String, Object>();
    14 
    15            map.put("img", R.drawable.hero);
    16 
    17            map.put("str", "aaa");
    18 
    19            data.add(map);
    20 
    21            map = new HashMap<String, Object>();
    22 
    23            map.put("img", R.drawable.hero);
    24 
    25            map.put("str", "bbb");
    26 
    27            data.add(map);
    28 
    29            map = new HashMap<String, Object>();
    30 
    31            map.put("img", R.drawable.hero);
    32 
    33            map.put("str", "ccc");
    34 
    35            data.add(map);
    36 
    37            map = new HashMap<String, Object>();
    38 
    39            map.put("img", R.drawable.hero);
    40 
    41            map.put("str", "ddd");
    42 
    43            data.add(map);
    44 
    45            map = new HashMap<String, Object>();
    46 
    47            map.put("img", R.drawable.hero);
    48 
    49            map.put("str", "eee");
    50 
    51            data.add(map);
    52 
    53           
    54 
    55            SimpleAdapter sa = new SimpleAdapter(this, data, R.layout.item_layout, new String[]{"img","str"}, new int[]{R.id.iv,R.id.tv_name});
    56 
    57            lv.setAdapter(sa);
    58 
    59 }

    显示结果:

     

    关于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()方法示例:

     1 ListView lv = (ListView) findViewById(R.id.listview);
     2 
     3            lv.setOnItemClickListener(new OnItemClickListener() {
     4 
     5                  @Override
     6 
     7                  public void onItemClick(AdapterView<?> parent, View view,
     8 
     9                             int position, long id) {
    10 
    11                       Log.i("listview","onClick");
    12 
    13                       Log.i("listview",view.toString());
    14 
    15                       Log.i("listview",position+"");
    16 
    17                       Log.i("listview",id+"");
    18 
    19                       TextView tv = (TextView) view.findViewById(R.id.tv_name);
    20 
    21                       Toast.makeText(MainActivity.this, tv.getText(), Toast.LENGTH_LONG).show();
    22 
    23                  }
    24 
    25            });

    运行结果:

     

    ListView先学到这,等学了数据库操作,也许会用到CursorAdapter等,用到时再学。

  • 相关阅读:
    ios开发-2015-07-19
    ios开发-2015-07-18
    ios开发-2015-07-17
    ios开发-2015-07-16
    ios开发-2015-07-15
    ios开发-2015-07-14
    ios开发-2015-07-13
    Selenium源码分析之WebDriver
    webdriver实现原理 分类: Selenium 2015-07-16 00:16 11人阅读 评论(0) 收藏
    webdriver实现原理
  • 原文地址:https://www.cnblogs.com/dqrcsc/p/4627620.html
Copyright © 2020-2023  润新知