«

安卓ListView控件详解

时间:2024-3-2 17:43     作者:韩俊     分类: Android


1.ArrayAdapter
这个是最简单的了,只默认接受TextView控件,而且还只是一个。

        listView = new ListView(this);   //注意没有使用XML文件的
        //样式是安卓提供的样式  
        listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));
        setContentView(listView);   


这个就表示没有使用XML文件,直接new一个ListView,android.R.layout.simple_expandable_list_item_1是安卓提供的样式。 getData()返回一个List<String>集合
虽然看起来没什么技术含量,但是如果要使用类似于这样的适配器,俩三句代码就完成了,不需要配置XML文件,只需要给一个集合就行了。



2.SimpleCursorAdapter(针对数据库服务,其实就是ContentProvider)
游标适配器,在贴代码之前解释一下Course,于是在网上找了一些资料,大致是这样的。


它的设计是基于数据库服务产生的
需要权限 <uses-permission android:name="android.permission.READ_CONTACTS" />
Cursor 是每行的集合。使用 moveToFirst() 定位第一行。你必须知道每一列的名称。你必须知道每一列的数据类型。Cursor 是一个随机的数据源。所有的数据都是通过下标取得。

关于 Cursor 的重要方法:

<span style="font-size:14px;">·close()——关闭游标,释放资源
·copyStringToBuffer(int columnIndex, CharArrayBuffer buffer)——在缓冲区中检索请求的列的文本,将将其存储
·getColumnCount()——返回所有列的总数
·getColumnIndex(String columnName)——返回指定列的名称,如果不存在返回-1
·getColumnIndexOrThrow(String columnName)——从零开始返回指定列名称,如果不存在将抛出IllegalArgumentException 异常。
·getColumnName(int columnIndex)——从给定的索引返回列名
·getColumnNames()——返回一个字符串数组的列名
·getCount()——返回Cursor 中的行数
·moveToFirst()——移动光标到第一行
·moveToLast()——移动光标到最后一行
·moveToNext()——移动光标到下一行
·moveToPosition(int position)——移动光标到一个绝对的位置
·moveToPrevious()——移动光标到上一行</span>
<span style="font-size:14px;">
访问 Cursor 的下标获得其中的数据
int nameColumnIndex = cur.getColumnIndex(People.NAME);
String name = cur.getString(nameColumnIndex);</span>

现在让我们看看如何循环 Cursor 取出我们需要的数据

<span style="font-size:14px;">while(cur.moveToNext()) {
    //光标移动成功
   String email = cursor.getString(cursor.getColumnIndex(RuiXin.EMAIL));
   startManagingCursor(cursor);  //查找后关闭游标 
   //把数据取出
}</span>


   /*  getApplicationContext():生命周期是整个应用,应用摧毁,它才摧毁。
             *  this:代表当前,在Activity当中就是代表当前的Activity,换句话说就是Activity.this在Activity当中可以缩写为this.
             *   getApplication():andorid 开发中共享全局数据;
             */
            listView = new ListView(this);

            //获取手机通讯录信息 这个和ContainProvider有关   

            Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
            startManagingCursor(cursor);   
            /* Cursor对象的生命周期便能与当前的Activity自动同步,省去了自己对Cursor的管理
             * 1.这个方法使用的前提是:游标结果集里有很多的数据记录。所以,在使用之前,先对Cursor是否为null进行判断,如果Cursor != null,再使用此方法
              2.如果使用这个方法,最后也要用stopManagingCursor()来把它停止掉,以免出现错误。
              3.使用这个方法的目的是把获取的Cursor对象交给Activity管理,这样Cursor的生命周期便能和Activity自动同步,省去自己手动管理。*/

            ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1, cursor,
                    new String[]{People.NAME}, new int[]{android.R.id.text1});
            listView.setAdapter(listAdapter);
            setContentView(listView);



3.SimpleAdapter
 /*
          这是一个简单的适配器,可以将静态数据映射到XML文件中定义好的视图。你可以指定由Map组成的List(比如ArrayList)类型的数据。在ArrayList中的每个条目对应List中的一行。Maps包含每一行的数据。你可以指定一个XML布局以指定每一行的视图,根据Map中的数据映射关键字到指定的视图。绑定数据到视图分两个阶段,首先,如果设置了SimpleAdapter.ViewBinder,那么这个设置的ViewBinder的setViewValue(android.view.View, Object, String)将被调用。如果setViewValue的返回值是true,则表示绑定已经完成,将不再调用系统默认的绑定实现。如果返回值为false,视图将按以下顺序绑定数据:
          如果View实现了Checkable(例如CheckBox),期望绑定值是一个布尔类型。
         TextView.期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)绑定。
         ImageView,期望绑定值是一个资源id或者一个字符串,通过调用setViewImage(ImageView, int) 或 setViewImage(ImageView, String)绑定数据。
          如果没有一个合适的绑定发生将会抛出IllegalStateException。
          */
         ListView listView=new ListView(this);
         SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,
                    new String[]{"title","info","img"},
                    new int[]{R.id.title,R.id.info,R.id.img});
         listView.setAdapter(adapter);
         setContentView(listView);


获取数据List<HashMap<String,Object>> getData()
   private List<Map<String, Object>> getData() {
            /*  对于SimpleAdapter这个来说,这个貌似是一成不变的 List<Map<String,Object>>
                    一个Map组成的List。在列表中的每个条目对应列表中的一行,每一个map中应该包含所有在from参数中指定的键

                context  SimpleAdapter关联的View的运行环境
                data    一个Map组成的List。在列表中的每个条目对应列表中的一行,每一个map中应该包含所有在from参数中指定的键
                resource    一个定义列表项的布局文件的资源ID。布局文件将至少应包含那些在to中定义了的ID
                from          一个将被添加到Map映射上的键名
                to     将绑定数据的视图的ID,跟from参数对应,这些应该全是TextView

              */
            List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("title", "科技");
            map.put("info", "人工智能何时达到奇点");
            map.put("img", R.drawable.i1);  //资源文件ID
            list.add(map);

            map = new HashMap<String, Object>();
            map.put("title", "社会");
            map.put("info", "到底扶不扶老人");
            map.put("img", R.drawable.i2);      
            list.add(map);

            map = new HashMap<String, Object>();
            map.put("title", "NBA");
            map.put("info", "西部决赛我希望是火箭赢");
            map.put("img", R.drawable.i3);
            list.add(map);

            return list;
        }




3.SimpleAdapter(可以自己发挥) 如果在一个ListView中添加按钮和图片,并给按钮添加事件。那么该如何,在List<HashMap<String,Object>>是不能将按钮添加进去的。 这就需要一个自己定义的适配器
<span style="white-space:pre"> </span>     listView = new ListView(this);
         mData = getData();  //获取数据
         MyAdapter adapter = new MyAdapter(this);
         listView.setAdapter(adapter);
         setContentView(listView);


自定义适配器需要继承BaseAdapter
public class MyAdapter extends BaseAdapter{

        /**
         * 作用类似于findViewById()
         * LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化;而findViewById()是找xml布局文件下的具体widget控件(如Button、TextView等)。
         * 1、对于一个没有被载入或者想要动态载入的界面,都需要使用LayoutInflater.inflate()来载入;
           2、对于一个已经载入的界面,就可以使用Activiyt.findViewById()方法来获得其中的界面元素。
         */
        private LayoutInflater mInflater;

        public MyAdapter(Context context){
            this.mInflater = LayoutInflater.from(context);  //实例化
        }
        @Override
        public int getCount() {
            return mData.size();
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            return 0;
        }

        /**
         * Adapter的作用就是ListView界面与数据之间的桥梁,当列表里的每一项显示到页面时,都会调用Adapter的getView方法返回一个View。 
         *   View的每次创建是比较耗时的,因此对于getview方法传入的convertView应充分利用 != null的判断
         *    
         *   优化listview的加载速度就要让convertView匹配列表类型,并最大程度上的重新使用convertView
         *   定义一个ViewHolder,将convetView的tag设置为ViewHolder,不为空时重新使用即可
         *   
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolder holder = null;
            if (convertView == null) {
                holder=new ViewHolder();  
            /*过载形式,返回值是 View 对象  
             *  public View inflate (int resource, ViewGroup root) 
                public View inflate (XmlPullParser parser, ViewGroup root)
                public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)  
                public View inflate (int resource, ViewGroup root, boolean attachToRoot)*/ 
                convertView = mInflater.inflate(R.layout.vlist2, null);
                holder.img = (ImageView)convertView.findViewById(R.id.img);
                holder.title = (TextView)convertView.findViewById(R.id.title);
                holder.info = (TextView)convertView.findViewById(R.id.info);
                holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
                convertView.setTag(holder);

            }else {
                holder = (ViewHolder)convertView.getTag();  //重新使用  匹配使用的
                /**就是一个持有者的类,他里面一般没有方法,只有属性,作用就是一个临时的储存器,把你getView方法中每次返回的View存起来,
                 * 可以下次再用。这样做的好处就是不必每次都到布局文件中去拿到你的View,提高了效率。
                 */
            }

            holder.img.setBackgroundResource((Integer)mData.get(position).get("img"));
            holder.title.setText((String)mData.get(position).get("title"));
            holder.info.setText((String)mData.get(position).get("info"));

            /**
             * 还能在这里添加事件响应,真绝了
             */
            holder.viewBtn.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    showInfo();                 
                }
            });
            return convertView;
        }

    }


ViewHolder相当于一个JavaBean, 只有属性没有方法



/**
     * 当处理一些耗时的资源加载的时候需要做到以下几点,以使你的加载更快更平滑:
        1.   适配器在界面主线程中进行修改
        2.   可以在任何地方获取数据但应该在另外一个地方请求数据
        3.   在主界面的线程中提交适配器的变化并调用notifyDataSetChanged()方法
     * @author suibian
     *
     */

    public final class ViewHolder{
        public ImageView img;
        public TextView title;
        public TextView info;
        public Button viewBtn;
    }


参照博客: http://www.cnblogs.com/allin/archive/2010/05/11/1732200.html#


我是菜鸟,我在路上。
2015年5月20日10:30:28

标签: android

热门推荐