第二章 吸引你的眼球—UI編程(5),第二章ui

來源:互聯網
上載者:User

第二章 吸引你的眼球—UI編程(5),第二章ui
2.1.7列表組件(ListView)

ListView在Android中也是一個使用比較頻繁的組件。它相對於其他的基本組件來說,使用起來稍微複雜一些,需要注意的也比較多,尤其是和其他一些組件組合起來使用的情況。

在Android中,ListView用來顯示一個列表的組件,它以列表的形式展示具體的內容,並且能夠根據資料的長度自適應顯示。使用者可以選擇並操作這個列表,同時會觸發相應的事件:當滑鼠滾動時會觸發setOnItemSelectedListener事件;當點擊列表時會觸發setOnItemClickListener事件。

列表的顯示需要三個元素:

1) ListView:用來展示列表的View;

2) 適配器:用來把資料對應到ListView上的中介;

3) 資料:具體的將被映射的字串、圖片或者其他基本組件。

根據列表的適配器類型,列表分為三種:ArrayAdapter、SimpleAdapter和SimpleCursorAdapter。其中以ArrayAdapter最為簡單,只能展示一行字;SimpleAdapter有最好的擴充性,可以自訂出各種效果;SimpleCursorAdapter可以認為是SimpleAdapter對資料庫的簡單結合,可以方便地把資料庫中的內容以列表的形式展示出來。

下面,我們分別以一個例子來看看這些ListView是如何?的。

1)首先,我們來看看ArrayAdapter,部分代碼如下:

private ListView listView;

 

    @Override

    public void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        listView = new ListView(this);

        listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData()));

        setContentView(listView);

    }

    

    private List<String> getData(){

        List<String> data = new ArrayList<String>();

        data.add("第一行");

        data.add("第二行");

        data.add("第三行");

        return data;

    }

 

讓我們來看看效果,2-15所示:

圖2-15 ArrayAdapter的使用

 

這種列表使用了ArrayAdapter(Context context,int textViewResourceId, List<T>objects)來裝配資料,ArrayAdapter的構造需要三個參數,依次為Context、布局檔案(注意這裡的布局檔案描述的是列表的每一行的布局,android.R.layout.simple_list_item_1是系統定義好的布局檔案只顯示一行文字,資料來源(一個List集合)。同時用setAdapter()完成適配。

2)SimpleCursorAdapter是把從遊標得到的資料進行列表顯示,並可以把指定的列映射到對應的TextView中。

下面的例子從電話簿中把連絡人顯示到類表中。先在通訊錄中添加一個連絡人作為資料庫的資料。然後獲得一個指向資料庫的Cursor並且定義一個布局檔案(當然也可以使用系統內建的)。

private ListView listView;

    

    @Override

    public void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        listView = new ListView(this);

        Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);

        startManagingCursor(cursor);

        ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1,

                cursor,

                new String[]{People.NAME},

                new int[]{android.R.id.name});

        listView.setAdapter(listAdapter);

        setContentView(listView);

    }

 

SimpleCursorAdapter 建構函式前面3個參數和ArrayAdapter是一樣的,最後兩個參數:一個包含資料庫的列的String型數組,一個包含布局檔案中對應組件id的int型數組。其作用是自動的將String型數組所表示的每一列資料對應到布局檔案對應id的組件上。上面的代碼,將NAME列的資料一次映射到布局檔案的id為name的組件上。

另外,讀取通訊錄需要在AndroidManifest.xml中如許可權:<uses-permissionandroid:name="android.permission.READ_CONTACTS"></uses-permission>。

效果2-16所示:

圖2-16 SimpleCursorAdapter的使用

 

3)SimpleAdapter是我們比較常用的一種列表。它的擴充性最好,可以定義各種各樣的布局出來,可以放上ImageView(圖片),還可以放上Button(按鈕),CheckBox(複選框)等等。我們也以一個例子來看看它是如何?的。

首先,我們定義一個list_item.xml檔案來定義list的內容:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="horizontal"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <TextView

        android:id="@+id/name_textview"

        android:layout_height="wrap_content"

        android:layout_width="100dp"/>

    <TextView

        android:id="@+id/phone_textview"

        android:layout_height="wrap_content"

        android:layout_width="150dp"/>

    <Button

        android:id="@+id/call_button"

        android:layout_height="wrap_content"

        android:layout_width="wrap_content"

        android:text="呼叫"/>

</LinearLayout>

 
在這裡,我們定義兩個TextView、一個Button按鈕,接著我們建立一個MyList類繼承自ListActivity(ListActivity類繼承Activity類,預設綁定了一個ListView(列表視圖)介面組件,並提供一些與列表視圖、處理相關的操作),部分代碼如下:

@Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.list_item,

                new String[]{"name","phone"},

                new int[]{R.id.name_textview,R.id.phone_textview});

        setListAdapter(adapter);

    }

 

    private List<Map<String, Object>> getData() {

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("name", "張三");

        map.put("phone", "13472345623");

        list.add(map);

 

        map = new HashMap<String, Object>();

        map.put("name", "李四");

        map.put("phone", "13472345623");

        list.add(map);

        map = new HashMap<String, Object>();

        map.put("name", "王五");

        map.put("phone", "13472345623");

        list.add(map);

        return list;

    }
 
下面,我們來看看效果,2-17所示:
 

圖2-17 SimpleAdapter的使用

 
當我們點擊按鈕時,需要進行一系列的操作,但是上面那樣做無法滿足我們的需求。這是因為按鈕是無法映射的,即使我們成功的用布局檔案顯示出了按鈕也無法添加按鈕的響應,這樣的話就需要我們做一些別的事情來監聽按鈕事件:
首先,需要定義一個類ViewHolder,它裡面定義列表中的三個組件: 

public final class ViewHolder{

        public TextView name;

        public TextView phone;

        public Button call;

    }

 
然後,我們定義一個mData用於儲存資料:
privateList<Map<String, Object>> mData;
 
接著,我們定義一個類MyAdapter繼承自BaseAdapter:

public class MyAdapter extends BaseAdapter{

 

        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;

        }

        @Override

        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolder holder = null;

            if (convertView == null) {

                holder=new ViewHolder(); 

                convertView = mInflater.inflate(R.layout.list_item, null);

                holder.name = (TextView)convertView.findViewById(R.id.name_textview);

                holder.phone = (TextView)convertView.findViewById(R.id.phone_textview);

                holder.call = (Button)convertView.findViewById(R.id.call_button);

                convertView.setTag(holder);

            }else {

                holder = (ViewHolder)convertView.getTag();

            }

holder.name.setText((String)mData.get(position).get("name"));

holder.phone.setText((String)mData.get(position).get("phone"));

holder.call.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                Log.d(“test”,“call the number”);

                }

            });

            return convertView;

        }

    }

 
最後是onCreate方法:

@Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mData = getData();

        MyAdapter adapter = new MyAdapter(this);

        setListAdapter(adapter);

    }

 
這樣的話,我們就可以對列表中的每一個組件進行事件監聽了。如果我們要對ListView的每一行的點擊事件進行監聽的話,我們需要實現OnItemClickListener介面中的onItemClick方法:

@Override

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

    Log.d("test", "item: "+ arg2);

}
 
上面介紹的是使用ListActivity方式,因為它預設綁定了一個ListView,所以我們並不需要自己定義ListView就能直接使用了,但是很多時候,我們可能是在布局中自己定義一個ListView,這樣我們可以自己來控制它的大小等屬性,例如:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="match_parent"

    android:layout_height="match_parent">

    <ListView

        android:id="@android:id/list"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"/>

</LinearLayout>
 
這裡需要注意的是,這個ListView的id必須為"@android:id/list",然後我們通過以下的代碼來實現:

AdapterView<?> mAdapterView = (ListView) findViewById(android.R.id.list);

((AbsListView) mAdapterView).setAdapter(adapter);

 
如果用這種方法的話,我們除了可以實現OnItemClickListener介面之外,也可以直接對ListView綁定監聽事件來達到處理點擊列表每一行的效果:

mAdapterView.setOnItemClickListener(new OnItemClickListener() {

    @Override

   public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

         Log.d("test", "item: "+arg2);

}

});

 

經驗分享:   

有的時候,我們為列表添加了OnItemClickListener監聽,但是點擊每一行後並沒有效果。這是因為,如果列表中有CheckBox或者是Button等存在的話,他們預設是獲得焦點的,而ListView的item能被選中的條件是要獲得焦點,因為我們在根控制項下設定如下屬性:

android:descendantFocusability="blocksDescendants",這樣Item Layout就屏蔽了所有子控制項擷取Focus的許可權,而自己能夠獲得焦點響應點擊事件了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.