• Android用户界面 UI组件--AdapterView及其子类(一) ListView及各种Adapter详解


    ListView就是列表组件,一般通过继承ListActivity使用系统提供的ListView.

    所有的AdapterView组件都需要有一个对应的Adapter作为适配器来显示列表中元素的布局方式

    见思维导图


    ArrayAdapter: 数组或集合的适配器。

    例:
    private final String[] mous = {
            "郭嘉",
            "荀攸",
            "荀彧",
            "程昱",
            "戏志才",
            "徐庶"
    };
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);


    也可以在XML文件中用android:entries属性指定绑定的数组资源文件
    资源文件存放在value文件夹下
    如:
    android:entries="@array/book"

    <string-array name="book" >
            <item >1</item>
            <item >2</item>
            <item >3</item>
            <item >3</item>
    </string-array>   


    例子

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
    
        <ListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    
    </LinearLayout>
    package com.light.android.study;
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    public class MainActivity extends Activity {
    		
    	    private final String[] mous = {
    	      "郭嘉",
    	      "荀攸",
    	      "荀彧",
    	      "程昱",
    	      "戏志才",
    	      "徐庶"
    	    };
    	    private ListView lv;
    	    
    		@Override
    		public void onCreate(Bundle savedInstanceState)
    		{
    			super.onCreate(savedInstanceState);
    			setContentView(R.layout.activity_main);
    			init();
    			initAdapter();
    		}
    
    		private void init(){
    			lv = (ListView) findViewById(R.id.lv);
    		}
    		
    		private void initAdapter(){
               ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mous);
               lv.setAdapter(adapter);
    		}
    		
    }
    


    效果:



    SimpleAdapter:简单的Adapter实现

    SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
    第一个参数是Context对象
    第二个参数是保存有每一行数据的Map构成的List对象,也就是说,每一行数据里的每一个属性都由它的名字和它的值构成一个键值对,多个属性有多个键值对,每一行的多个键值对构成这一行的一个Map对象,这一行的Map对象对应到这个List中.
    第三个参数布局文件Id
    第四个参数Map对象中的多个键值对的key值
    第五个参数布局文件中用来显示内容的组件ID


    SimpleAdapter绑定数据到视图分两个阶段
    1.首先,如果设置了SimpleAdapter.ViewBinder,那么这个设置的ViewBinder的setViewValue(android.view.View, Object, String)将被调用.如果setViewValue的返回值是true,则表示绑定已经完成,将不再调用系统默认的绑定实现.
    2.如果返回值为false,视图将按以下顺序绑定数据:
    •如果View实现了Checkable(例如CheckBox),期望绑定值是一个布尔类型.
    •TextView.期望绑定值是一个字符串类型,通过调用setViewText(TextView, String)绑定.
    •ImageView,期望绑定值是一个资源id或者一个字符串,通过调用setViewImage(ImageView, int) 或 setViewImage(ImageView, String)绑定数据.
    如果没有一个合适的绑定发生将会抛出IllegalStateException.

    例子:

    布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <!-- 定义一个List -->
    
        <ListView
            android:id="@+id/mylist"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        
    </LinearLayout>
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    
        <!-- 定义一个ImageView,用于作为列表项的一部分。 -->
    
        <ImageView
            android:id="@+id/header"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            tools:ignore="ContentDescription" />
    
        <!-- 定义一个TextView,用于作为列表项的一部分。 -->
    
        <TextView
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center_vertical"
            android:paddingLeft="10dp"
            android:textSize="16sp" />
    
    </LinearLayout>
    package com.light.android.study;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.ListView;
    import android.widget.SimpleAdapter;
    
    public class MainActivity extends Activity {
    	private String[] names = new String[] { "杜甫", "弄玉", "清照", "李白" };
    	private int[] imageIds = new int[] { R.drawable.tiger, R.drawable.nongyu,
    			R.drawable.qingzhao, R.drawable.libai };
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
    		for (int i = 0; i < names.length; i++) {
    			Map<String, Object> map = new HashMap<String, Object>();
    			map.put("header", imageIds[i]);
    			map.put("personName", names[i]);
    			listItems.add(map);
    		}
    		
    		//創建SimpleAdapter
    		SimpleAdapter simpleAdapter = new SimpleAdapter(this, listItems,
    				R.layout.list_item_layout, new String[] { "personName", "header" },
    				new int[] { R.id.name, R.id.header });
    		
    		ListView list = (ListView) findViewById(R.id.mylist);
    		list.setAdapter(simpleAdapter);
    	}
    }
    


    效果:



    CursorAdapter:

    Cursor型集合的适配器,与数据库连接的桥梁
    其中游标携带的结果集中必须有列名为“_id”的列,否则这个类无法工作.
    getView()
    每一项显示的设置
    bindView()
    把数据和已经生成的View绑定在一起
    newView()
    新建一个View
    CursorAdapter中源码 getView的实现
    public View getView(int position, View convertView, ViewGroup parent) {
     View v;
     if (convertView == null) {
       v = newView(mContext, mCursor, parent);
     } else {
       v = convertView;
     }
     bindView(v, mContext, mCursor);
     return v;
    }
    getView首先使用已经存在的View,如果没有就调用newView 产生一个,然后把数据bind上去

    我们一般使用其子类SimpleCursorAdapter来实现查询出来的数据List的Adapter

    SimpleCursorAdapter(Context context,int layout,Cursor c,String[] from,int[] to,int flags)
    context:当前Context对象
    layout:布局文件Id
    c:集合
    from:需要绑定的集合中的列的名字
    to:显示项目的View的id集合,在layout布局文件中定义
    flags:用来判断适配器的行为标志
    建议使用CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
    适配器会在游标上注册一个内容观测器,当通知到达时会调用 onContentChanged() 方法.使用该标志位时要注意:在注册观察器时需要先解除当前游标与适配器的关联,防止发生泄漏.
    Android 3.0引入了CursorLoader实现异步加载数据,为了避免同步查询数据库时阻塞UI线程的问题。所以一般先将SimpleCursorAdapter中的Cursor对象放空,然后用CursorLoader对象加载数据,再放入适配器。
    例子:

    布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
    
        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    
    </LinearLayout>

    Item布局文件:

    <?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:tools="http://schemas.android.com/tools"
                  android:layout_width="match_parent" 
                  android:layout_height="64dip" 
                  android:orientation="horizontal" 
                  android:gravity="center_vertical" 
                  android:paddingLeft="8dip">
                   
                   <TextView android:id="@android:id/text1" 
                             android:layout_width="match_parent"
                             android:layout_height="wrap_content" 
                             android:textSize="18sp" 
                             android:gravity="center_vertical" 
                             android:singleLine="true" 
                             android:fadingEdge="horizontal" 
                             android:fadingEdgeLength="3dip" 
                             android:ellipsize="marquee" 
                             /> 
    </LinearLayout>
    package com.light.android.study;
    
    import android.app.ListActivity;
    import android.app.LoaderManager.LoaderCallbacks;
    import android.content.Context;
    import android.content.CursorLoader;
    import android.content.Loader;
    import android.database.Cursor;
    import android.os.Bundle;
    import android.provider.ContactsContract;
    import android.widget.SimpleCursorAdapter;
    
       //實現接口作為CursorLoader
    public class MainActivity extends ListActivity implements LoaderCallbacks<Cursor> {
    	private SimpleCursorAdapter mAdapter;
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		// Create an empty adapter we will use to display the loaded data. 
    		mAdapter = new SimpleCursorAdapter(MainActivity.this,
    				R.layout.contacts_list_item, null,
    				new String[] { ContactsContract.Contacts.DISPLAY_NAME },
    				new int[] { android.R.id.text1 },
    				0);
    		
    		getListView().setAdapter(mAdapter);
    		
    		//初始化Loader
    		//第一個參數 為這個Loader對象指定唯一的标识ID,第二个可选参数,用来支持Loader的构造方法,
    		//第三个参数是LoaderCallbacks接口类型
    		getLoaderManager().initLoader(0, null, this);
    	}
    
    	public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    		// 去数据库读取数据等要消耗大量时间的操作放在 
    		// 自定义 CursorLoader 的 onLoadInBackground
    		return new MyCursorLoader(getApplicationContext());
    	}
    
    	
    	public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
    		// Swap the new cursor in.  (The framework will take care of closing the         
    		// old cursor once we return.) 
    		mAdapter.swapCursor(cursor); 
    	}
    
    	public void onLoaderReset(Loader<Cursor> arg0) {
    		// This is called when the last Cursor provided to onLoadFinished()        
    		// above is about to be closed.  We need to make sure we are no         
    		// longer using it. 
    		mAdapter.swapCursor(null);
    	}
    
    	public static class MyCursorLoader extends CursorLoader {
    		String[] mContactProjection = { ContactsContract.Contacts._ID,
    				ContactsContract.Contacts.DISPLAY_NAME };
    		private Context mContext;
    
    		public MyCursorLoader(Context context) {
    			super(context);
    			mContext = context;
    		}
    
    		/**
    		 * 4.自定义 CursorLoader 的 onLoadInBackground
    		 * 会返回一个Cursor,这里给SimpleCursorAdapter用 
    		 * 来填充数据。查询数据等操作放在这里执行
    		 */
    		@Override
    		protected Cursor onLoadInBackground() {
    			Cursor cursor = mContext.getContentResolver().query(
    					ContactsContract.Contacts.CONTENT_URI, mContactProjection,
    					null, null, null);
    			return cursor;
    		}
    	}
    }
    


    效果:


    最后看下自定义BaseAdapter

    需要实现下列方法:

    abstract Object getItem(int position)
    得到位于position位置的项
    abstract int getCount()
    得到项目总数
    abstract long getItemId(int position)
    得到位于position位置的项的Id
    abstract int getItemViewType(int position)
    得到位于position位置的项的类型
    abstract View getView(int position,View convertVeiw,ViewGroup parent)
    每一项显示的设置
    在getView方法中需要缓存加载View优化ListView

    官方建议使用ViewHolder,其实就是单例
    例:

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ViewHolder holder; 
     if (convertView == null) {
         final LayoutInflater inflater = (LayoutInflater)                        mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
         convertView = inflater.inflate(R.layout.list_item_icon_text, null); 
          holder = new ViewHolder();  
          holder.icon = (ImageView) convertView.findViewById(R.id.icon); 
          holder.text = (TextView) convertView.findViewById(R.id.text); 
          convertView.setTag(holder); 
     } else { 
          holder = (ViewHolder) convertView.getTag(); 
     } 
          holder.icon.setImageResource(R.drawable.icon); 
          holder.text.setText(mData[position]); 
          return convertView; 
    } 
    static class ViewHolder { 
        ImageView icon; 
        TextView text; 
    } 








     



     




     

  • 相关阅读:
    redis 持久化
    Linux 配置 FastDFS
    查询相关
    外键查询
    pycharm 使用git
    比较时间
    文件导入import
    切分,字符串转列表
    时间相关
    django 自带序列化组件效果
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3279659.html
Copyright © 2020-2023  润新知