zoukankan      html  css  js  c++  java
  • 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; 
    } 








     



     




     

  • 相关阅读:
    POJ 2251 Dungeon Master
    HDU 3085 Nightmare Ⅱ
    CodeForces 1060 B Maximum Sum of Digits
    HDU 1166 敌兵布阵(树状数组)
    HDOJ 2050 折线分割平面
    HDU 5879 Cure
    HDU 1878 欧拉回路
    HDU 6225 Little Boxes
    ZOJ 2971 Give Me the Number
    HDU 2680 Choose the best route
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3279659.html
Copyright © 2011-2022 走看看