首頁 php教程 PHP开发 listview與adapter用法

listview與adapter用法

Dec 13, 2016 pm 04:21 PM

一個ListView通常有兩個職責。

(1)將資料填入版面。

(2)處理使用者的選擇點擊等操作。

第一點很好理解,ListView就是實現這個功能的。第二點也不難做到,在後面的學習中讀者會發現,這非常簡單。

一個ListView的創建需要3個元素。

(1)ListView中的每一列的View。

(2)填入View的資料或圖片等。

(3)連接資料與ListView的適配器。

也就是說,要使用ListView,首先要了解什麼是適配器。適配器是一個連接資料和AdapterView(ListView就是一個典型的AdapterView,後面還會學習其他的)的橋樑,透過它能有效地實現資料與AdapterView的分離設置,使AdapterView與資料的綁定更加簡便,修改更加方便

Android提供了很多的Adapter,表4-5列出了常用的幾個。

表4-5 常用適配器

Adapter

   

意義

   

用來綁定一個陣列,支援泛型運算

   

SimpleAdapter

   

用來綁定在xml中定義的控制對應的資料

   

標得到的資料

   

BaseAdapter

   

通用的基本轉接器

   

 

 其實時只有一個不同的能力只是注意下面就透過使用不同的Adapter來為ListView綁定資料(SimpleCursorAdapter暫且不講,後面講SQLite時會介紹)。

4.12.1 ListView使用ArrayAdapter

用ArrayAdapter可以實現簡單的ListView的資料綁定。預設情況下,ArrayAdapter綁定每個物件的toString值到layout中預先定義的TextView控制項上。 ArrayAdapter的使用非常簡單。

實例:

工程目錄:EX_04_12

在版面配置檔案中加入一個ListView控制項。

http://schemas.android.com/apk/res/android"     and? 。  LinearLayout>

然後在Activity中初始化。

publicclass MyListView extends Activity {

   

privatestaticfinal String[] strs = new String[] {

   "first", "second", "third", "

   "first", "second", "third", "

   "first", "second", "third", "

   "first", "second", "third", "

   "first", "second", "third", "

來顯示ListView的內容private ListView lv;/**在第一次創建活動時調用。*/

@Override
publicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
ListView) findViewById(R.id.lv);//得到ListView物件的引用/*為ListView設定Adapter來綁定資料*/ 
lv.setAdapter(new ArrayAdapter(this,
         simple_list_item_1, strs));

   }

}






▲圖4-29 ListView使用ArrayAdapter運作效果。

 

分析一下所使用的步驟。

(1)定義一個陣列來存放ListView中item的內容。

(2)透過實作ArrayAdapter的建構子來建立一個ArrayAdapter的物件。

(3)透過ListView的setAdapter()方法綁定ArrayAdapter。

其中第二步有必要說一下的是,ArrayAdapter有多個建構函數,例子中實現的是最常用的一種。第一個參數為上下文,第二個參數為一個包含TextView,用來填入ListView的每一行的佈局資源ID。第三個參數為ListView的內容。其中第二個參數可以自訂一個layout,但是這個layout必須要有TextView控制項。通常我們會使用Android提供的資源,除了範例所使用的,常用的還有下列幾種,可實作帶有RadioButton和CheckBox的ListView。 listview與adapter用法

(1)透過指定android.R.layout.simple_list_item_checked這個資源,實作帶有選擇框的ListView。需要用setChoiceMode()方法設定選擇為多選還是單選,否則將無法實現選擇效果,運行效果如圖4-30所示。

實作程式碼如下:

lv.setAdapter(new ArrayAdapter(this,
               android.R.layout.simple_list_item        android.R.layout.simple_list_itemICE_checked, ).

 (2)透過指定android.R.layout.simple_list_item_multiple_choice這個資源實作帶有CheckBox的ListView。同樣的,需要用setChoiceMode()方法來設定單選或多選,運行效果如圖4-31所示。

實作程式碼如下:

lv.setAdapter(new ArrayAdapter(this,

               android.R.layout.simple_list_item_multian_oem_sad);



(3)透過指定android.R.layout.simple_list_item_single_choice這個資源實作帶有RadioButton的ListView。這裡要注意的是,這裡並不是指定了單選。是多重選擇還是單選要透過setChoiceMode()方法來指定,運行效果如圖4-32所示。

實作程式碼如下:

 

lv.setAdapter(newArrayAdapter(this,

android.R.layout.simple_list_item_singleView_choice,strs));

 




▲圖4-30 帶選擇框的ListView                        View                  ▲圖4-32 帶RadioButton的ListView

 前面講過,ListView的職責除了填資料外,還要處理用戶的操作。透過如下的程式碼就可以為ListView綁定一個點擊監聽器,點擊後在標題列顯示點擊的行數。 带选择框的ListView

lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2,                    long arg3) {                    //点击后在标题上显示点击了第几行                     setTitle("你点击了第"+arg2+"行");
            }
        });
登入後複製
带CheckBox的ListView         4.12.2 ListView使用SimpleAdapterlistview與adapter用法

很多時候需要在清單中展示一些除了文字以外的東西,例如圖片等。這時候可以使用SimpleAdapter。 SimpleAdapter的使用也非常簡單,同時它的功能也非常強大。可以透過它自訂ListView中的item的內容,例如圖片、多重選取框等。看一個例子,實作一個每一行都有一個ImageView和TextView的ListView。先看一下運行效果,如圖4-34所示。

▲圖4-34 帶圖示的ListView

 

首先在版面配置檔案中增加一個ListView控制項。 listview與adapter用法

 還需要定義一個ListView中每一行的佈局,用RelativeLayout來實作一個兩行字和一個圖片的佈局。

item.xml:

android: layout_height="fill_parent" android:layout_width="fill_parent"> 

android:layout_height="wproid;

android:layout_width="fill_parent" android:textSize="20sp"/Text>

android:layout_width="fill_parent" android:layout_below="@+id/ItemTitle" />


 綁定完畢,就可以設定完資料。

publicclass MyListViewSimple extends Activity {    
   private ListView lv;    /**在第一次創建活動時調用。*/ @Override
publicvoid onCreate(Bundle savedInstanceStateState) {super. (R.layout.main);

lv = (ListView) findViewById(R.id.lv);/*定義動態陣列*/          
ArrayList> listItem = new ArrayList> listItem = new ArrayList存放資料*/
for(int i=0;i<10;i++)  
       {  
           HashMap map = new HashMap<,    HashMap map = new HashMap<,    ("​​ItemImage", R. drawable.icon);//加入圖片            map.put("ItemTitle", "第"+i+"行");  
           map.put("ItemItem", "這是第一個吧   Item .add(map);  
       }

       SimpleAdapter mSimpleAdapter = new SimpleAdapter(this,listItem,///需要綁定的資料  Adapter = new SimpleAdapter(this,listItem,///需要//動態數組中的資料來源的鍵對應到定義版面的View中new String[] {"ItemImage"
,"ItemTitle", "ItemText"},  
newint[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText} 
);

lv.setAdapter(mSimpleAdapter);//為ListView綁定適配器 lv.setOnItemClickListener(new 
OnItemClickListener() {
  lick(AdapterView arg0, View arg1, int arg2,                    long arg3 ) {
               setTitle("你點選了第"+arg2+"行");//設定標題欄顯示點擊的行          );
   }
}


 使用simpleAdapter的資料一般都是用HashMap構成的列表,列表的每一節對應ListView的每一行。透過SimpleAdapter的建構函數,將HashMap的每個鍵的資料對應到佈局檔案中對應控制項上。這個佈局文件一般是根據自己的需求來自己定義。梳理一下使用SimpleAdapter的步驟。

(1)根據需要定義ListView每行所實現的佈局。

(2)定義一個HashMap構成的列表,將資料以鍵值對的方式存放在裡面。

(3)建構SimpleAdapter物件。

(4)將LsitView綁定到SimpleAdapter上。

4.12.3 ListView使用BaseAdapter與ListView的最佳化

在ListView的使用中,有時候還需要在裡面加入按鈕等控件,實現單獨的操作。也就是說,這個ListView不再只是展示數據,也不只是這一行要來處理使用者的操作,而是裡面的控制項要獲得使用者的焦點。讀者可以試試用SimpleAdapter添加一個按鈕到ListView的條目中,會發現可以添加,但是卻無法獲得焦點,點擊操作被ListView的Item所覆蓋。這時候最方便的方法就是使用靈活的轉接器BaseAdapter了。

▲圖4-35 BaseAdapter中的方法

使用BaseAdapter必須寫一個類別繼承它,同時BaseAdapter是一個抽象類,繼承它必須實現它的方法。 BaseAdapter的彈性就在於它要重寫很多方法,看看有哪些方法,如圖4-35所示為繼承自BaseAdapter的SpeechListAdapter所實作的方法,其中最重要的即為getView()方法。這些方法都有什麼作用呢?我們透過分析ListView的原理來為讀者解答。

 

当系统开始绘制ListView的时候,首先调用getCount()方法。得到它的返回值,即ListView的长度。然后系统调用getView()方法,根据这个长度逐一绘制ListView的每一行。也就是说,如果让getCount()返回1,那么只显示一行。而getItem()和getItemId()则在需要处理和取得Adapter中的数据时调用。那么getView如何使用呢?如果有10000行数据,就绘制10000次?这肯定会极大的消耗资源,导致ListView滑动非常的慢,那应该怎么做呢?通过一个例子来讲解如何在使用BaseAdapter的时候优化ListView的显示。例子中将上一节中的ImageView换成Button,并且处理Button的点击事件,其中对ListView的显示做了优化。

布局文件和上一例类同,读者可以在光盘的工程目录中查看,这里只给出Activity类。

publicclass MyListViewBase extends Activity {    
    private ListView lv;    /*定义一个动态数组*/     ArrayList<HashMap<String, Object>>listItem;/** Called when the activity is first created. */ 
@Override
publicvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

lv = (ListView) findViewById(R.id.lv);
        MyAdapter mAdapter = new MyAdapter(this);//得到一个MyAdapter对象 lv.setAdapter(mAdapter);//为ListView绑定Adapter /*为ListView添加点击事件*/ 
lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            publicvoid onItemClick(AdapterView<?> arg0, View arg1, int arg2,                    long arg3) {
        Log.v("MyListViewBase", "你点击了ListView条目" + arg2);//在LogCat中输出信息                 
            }
        });

    }/*添加一个得到数据的方法,方便使用*/ private ArrayList<HashMap<String, Object>> getDate(){
    
    ArrayList<HashMap<String, Object>> listItem = new ArrayList<HashMap<String,     Object>>();    /*为动态数组添加数据*/     for(int i=0;i<30;i++)  
         {  
             HashMap<String, Object> map = new HashMap<String, Object>();  
             map.put("ItemTitle", "第"+i+"行");  
             map.put("ItemText", "这是第"+i+"行");  
             listItem.add(map);  
         } 
        return listItem;
    
    }/*      * 新建一个类继承BaseAdapter,实现视图与数据的绑定     */ privateclass MyAdapter extends BaseAdapter {    private LayoutInflater mInflater;//得到一个LayoutInfalter对象用来导入布局  /*构造函数*/ 
public MyAdapter(Context context) {    this.mInflater = LayoutInflater.from(context);
        }

        @Override
        publicint getCount() {            
            return getDate().size();//返回数组的长度         }

        @Override        public Object getItem(int position) {
            returnnull;
        }

        @Override
        publiclong getItemId(int position) {            return 0;
        }        /*书中详细解释该方法*/         @Override        public View getView(finalint position, View convertView, ViewGroup parent) {
             ViewHolder holder;            //观察convertView随ListView滚动情况              
Log.v("MyListViewBase", "getView " + position + " " + convertView);            if (convertView == null) {
                     convertView = mInflater.inflate(R.layout.item,    null);
                     holder = new ViewHolder();                    /*得到各个控件的对象*/                    
 holder.title = (TextView) convertView.findViewById(R.id.ItemTitle);
                    holder.text = (TextView) convertView.findViewById(R.id.ItemText);
                    holder.bt = (Button) convertView.findViewById(R.id.ItemButton);
                    convertView.setTag(holder);//绑定ViewHolder对象                    }    else{
                    holder = (ViewHolder)convertView.getTag();//取出ViewHolder对象                   }            /*设置TextView显示的内容,即我们存放在动态数组中的数据*/             
holder.title.setText(getDate().get(position).get("ItemTitle").toString());
            holder.text.setText(getDate().get(position).get("ItemText").toString());            
            /*为Button添加点击事件*/              holder.bt.setOnClickListener(new OnClickListener() {
                
                @Override
                publicvoid onClick(View v) {
                Log.v("MyListViewBase", "你点击了按钮" + position);                                //打印Button的点击信息                     
                }
            });            
            return convertView;
        }
    
    }/*存放控件*/ publicfinalclass ViewHolder{    public TextView title;    public TextView text;    public Button   bt;
    }
}
登入後複製

 运行效果如图4-36所示。还需要注意的是,Button会抢夺ListView的焦点,需要将Button设置为没有焦点。设置非常简单,只需要在xml的Button标签下加入一行:android:focusable=“false”代码就可以了。在LogCat观察点击后输出的信息,如图4-37所示。

listview與adapter用法

▲图4-36 listview與adapter用法

listview與adapter用法

 ▲图4-37 listview與adapter用法

代码中getView()方法不容易理解。其实完全可以不用所谓的convertView和ViewHolder,直接导入布局并且设置控件显示的内容就可以了。但是这意味着有多少行数据就需要绘制多少行ListView,这显然是不可取的。这里采用了一种优化的方法。代码中,在getView()方法中加入了一行log输出convertView的内容。滚动ListView,输出信息如图4-38所示。

从图4-38中可以看出,当启动Activity呈现第一屏ListView的时候,convertView为零。当用户向下滚动ListView时,上面的条目变为不可见,下面出现新的条目。这时候convertView不再为空,而是创建了一系列的convertView的值。当又往下滚一屏的时候,发现第11行的容器用来容纳第22行,第12行的容器用来容纳第23行。也就是说convertView相当于一个缓存,开始为0,当有条目变为不可见,它缓存了它的数据,后面再出来的条目只需要更新数据就可以了,这样大大节省了系统资料的开销。

还可以继续优化。虽然重复利用了已经绘制的view,但是要得到其中的控件,需要在控件的容器中通过findViewById的方法来获得。如果这个容器非常复杂,这显然会增加系统资源的开销。在上面的例子中,引入了Tag的概念。或许不是最好的办法,但是它确实能使ListView变得更流畅。代码中,当convertView为空时,用setTag()方法为每个View绑定一个存放控件的ViewHolder对象。当convertView不为空,重复利用已经创建的view的时候,使用getTag()方法获取绑定的ViewHolder对象,这样就避免了findViewById对控件的层层查询,而是快速定位到控件。

listview與adapter用法

▲图4-38 listview與adapter用法

总结一下,这节介绍了用BaseAdapter来绑定ListView的数据。因为BaseAdapter非常灵活,使用也相对较其他控件麻烦。同时ListView的优化问题也值得读者去研究,一个流畅的ListView会带来更好的用户体验。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)