Android學習筆記(十七):再談ListView

來源:互聯網
上載者:User

由於手機螢幕尺寸的原因以及手指觸屏操作的特性,ListView常常用到。在Android學習筆記(十一):Activity-ListView中,每一個list中的entry只有一個資料,且都只涉及一個view,在本次,我們將學習進一步的變化,讓list更為生動,這隻需對apdater作進一步的描述。

例子一:每個元素有一個表徵圖和一個資訊資料

1)設定主介面的XML檔案

<LinearLayout ...>
  <!--  我們需要對list的entry進行地功能之,所以id採用"@android:id/list" -->
  <ListView android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" /> 
</LinearLayout>

2)設定每個元素格式entry.xml格式

<LinearLayout ...>
  <!-- 在每一個元素中(每一行list中),有一個image icon,然後是我們的資料資訊 -->
  <ImageView android:id="@+id/c82_icon"
    android:layout_width="44px"
    android:paddingLeft="2px"
    android:paddingRight="2px"
    android:paddingTop ="10px"
    android:layout_height="wrap_content"
    android:src="@drawable/android_normal" />
   <TextView android:id="@+id/c82_label"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:textSize="44sp" />
</LinearLayout>

3)原始碼

原始碼很簡單,可以參考Android學習筆記(十一):Activity-ListView中的第一個例子。不同的是設定adapter的寫法,原來的例子採用了android提供UI格式android.R.layout.simple_list_item_1,在這個例子中我們將採用自訂的layout格式來描述list增個中的元素:

public class Chapter8Test2 extends ListActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chapter_8_test2);
       /* 第一個參數是context,最後一個參數是資料資訊來源item,第二個參數是描述entry的layout xml檔案,第三個參數是資料資訊來源對應元素layout中的哪一個widget。*/
        setListAdapter ( new ArrayAdapter<String>( this,R.layout.entry,R.id.c82_label,Chapter8.items));
    }
   
    public void onListItemClick(ListView parent, View view, int position, long id){
        Toast.makeText(getApplicationContext(), Chapter8.items[position], Toast.LENGTH_SHORT).show();

    }

例子二:根據layout xml檔案,動態設定每個元素

上面的方式可以處理簡單的方式,但是下面兩種情況

  • 不是所有的單元都使用同一個layout
  • 需要設定在list單元中的widget,例如使用不同的icon

我們需要建立adapter的子類,通過重寫getView()來描述自己的單元風格。在下面的例子中,我們對第一個例子進行修改,對於長短不同的單詞,使用不同的icon。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chapter_8_test2);
        setListAdapter(new IconicAdapter());
    }
   
    private class IconicAdapter extends ArrayAdapter<String>{
        /* 步驟1:編寫建構函式,對於第一個例子,我們填入格式layout xml檔案和資料來源,以便完成必要的初始化工作 */
        IconicAdapter(){
            super(Chapter8Test3.this,R.layout.entry,Chapter8.items);
        }

        /*步驟2:通過重寫getView(),具體描述每個元素的格式,輸入中position表示list的順序位置,我們返回的View即使list在position位置的元素的呈現 */
        public View getView(int position, View convertView, ViewGroup parent) {
            /* 步驟2.1:根據layout xml檔案,通過LayoutInflater影射到一個View對象,作為我們list元素UI的基礎 */
            //LayoutInflater類是用於將layout XML檔案執行個體化為相應的view對象,它從不直接使用,而是使用getLayoutInflater()或者getSystemService(String)來獲得已掛在當前context標準的LayoutInflater執行個體。例如:LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             LayoutInflater infalter = getLayoutInflater();
             //從第一個參數獲得相關的XML的結構,第二個參數是ViewGroup root,最後一個參數表示如果有錯誤,是否扔出InflateException。
             View row=infalter.inflate(R.layout.entry, parent,
false
)
;
            
             /* 步驟2.2:具體設定每個View中各個widget的格式和資訊 ,在這個例子中,如果資訊長度大於4顯示一種表徵圖,小於等於顯示另一種表徵圖*/
             TextView label=(TextView)row.findViewById(R.id.c82_label);
             ImageView icon = (ImageView)row.findViewById(R.id.c82_icon);         

             label.setText(Chapter8.items[position]);
             if(Chapter8.items[position].length() > 4){
                 icon.setImageResource(R.drawable.android_focused);
             }else{
                 icon.setImageResource(R.drawable.android_normal);
             }
             /*步驟2.3,返回對應position位置的view */          

             return row;
        }
   }

例子三:讓程式更有效率

例子二可以靈活設定每一個list元素的UI,但是在效率方面,每次滑動,都需要根據getView()來擷取view,這對於快速移動時,會出現獃滯緩慢的現象,同時每次CPU的計算也消耗手機電池。在getView()中,有一個參數為View convertView,當我們第一次給出這個元素的UI的View時,convertView為零,此後convertView為我們之前所建立的view對象(重複利用,也避免java在garbage收集時消耗CPU[消耗電源])。可以重複利用我們之前建立的View,如果需要對內容進行改變,可以通過findViewById獲得對應的widget對象,對內容進行設定,這樣UI只重新整理設定的部分。下面是例子三對例子二中getView的修改。

        /*為了是程式更有效率,利用之前已經建立的View(即第二個參數),只有第一次顯示該元素時,方建立新的View*/
        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            //在這個例子中,由於widget的內容不變, 可以在第一次設定中賦值。在本例子中我們按動態顯示(需要處理其中的變化),將內容每次都重新設定
            if(row == null){
                LayoutInflater inflater = getLayoutInflater();
                row = inflater.inflate(R.layout.chapter_8_test2_entry,parent,false);
            }    
            TextView label=(TextView)row.findViewById(R.id.c82_label);
            label.setText(Chapter8.items[position]);
           
            ImageView icon = (ImageView)row.findViewById(R.id.c82_icon);
             label.setText(Chapter8.items[position]);
             if(Chapter8.items[position].length() > 4){
                 icon.setImageResource(R.drawable.android_focused);
             }else{
                 icon.setImageResource(R.drawable.android_normal);
             }
       
             return row;
        }

例子四:讓程式進一步有效率 setTag( )

在上面的例子,我們重複利用了已建立的View,但是findViewById需要在View的層次中尋找,如果View的結構複雜,同樣也是消耗CPU的。此外對於每個List元素,在實際的程式中,list元素可能還會儲存某些資料。在這個例子,我們引入setTag()和getTag()兩個方法。每個View都可以通過setTag()綁帶一個object,可以通過getTag()將這個object取出來,這樣可以避免findViewById對widget的層層查詢,做到快速定位。

//步驟一:設定一個class用來儲存list元素的資訊
    class ViewWrapper{
        View base;
        TextView label = null;
        ImageView icon = null;
       
        ViewWrapper(View base){
            this.base = base;
        }
       
        TextView getLabel(){
            if(label == null)
                label = (TextView)base.findViewById(R.id.c82_label);
            return label;
        }
       
        ImageView getIcon(){
            if(icon == null)
                icon = (ImageView)base.findViewById(R.id.c82_icon);
            return icon;
        }
    }
  
   ... ...餘下內容同例子2和例子3,我們重寫IconicAdapter的getView()

        public View getView(int position, View convertView, ViewGroup parent) {
            View row = convertView;
            ViewWrapper wrapper = null;
            //步驟2:如果沒有建立View,建立之,並通過setTag()捆綁ViewWrapper對象,如果已經建立,通過getTag()擷取ViewWrapper對象。
            if(row == null){
                LayoutInflater inflater = getLayoutInflater();
                row = inflater.inflate(R.layout.chapter_8_test2_entry,parent,false);
                wrapper = new ViewWrapper(row);
                row.setTag(wrapper);
            }else{
                wrapper = (ViewWrapper) row.getTag();
            }
           
            wrapper.getLabel().setText(Chapter8.items[position]);       

             if(Chapter8.items[position].length() > 4){
                 wrapper.getIcon().setImageResource(R.drawable.android_focused);
             }else{
                 wrapper.getIcon().setImageResource(R.drawable.android_normal);
             }
       
             return row;
        }
    }

相關連結:我的Andriod開發相關文章

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.