Android快速入門之使用AdapterView展示不同風格的列表

龍源IT發表於2020-12-17

在物件導向的程式設計中接觸過MVC模式,其實現原理:資料模型M(Model)負責存放資料,通過控制器C(Controller)將資料顯示到相應的試圖上(View)。在Android中也有類似的控制元件,它不像之前的控制元件那樣拖拽到介面上,而是通過介面卡將某些樣式的資料新增到其上使用,這樣的控制元件就是AdapterView。

常用的AdapterView控制元件

AdapterView元件作為一組非常重要的元件,主要以列表形式展示多個具有相同風格式的資源。常用的AdapterView有:AutoCompleteTextView(自動提示控制元件)、Spinner(下拉選單)、ListView(列表)、GriView(網格圖)等…

AutoCompleteTextView控制元件:

AutoCompleteTextView類繼承自EditText類,與EditText控制元件是一樣的,當使用者輸入了與事先為該控制元件定義的一組字串集中相關的資訊時,才會出現下拉選項,供使用者選擇。

使用方式:

String[] contents = new String[]{"Student","Student1", "student2","AAA","ST1","dut","學生","User", "tv","Study","study","yyy"};
    
ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this,
                //Android中自帶的佈局
                android.R.layout.simple_expandable_list_item_1,
                //這裡用String陣列表示,也可以來源於檔案或資料庫
                contents);
//輸入2個字母就開始自動提示
autoTextView.setThreshold(2);

Spinner控制元件:

Spinner下拉選單,外觀是一個一行的列表框,使用者單擊控制元件,下拉出選項列表供使用者選擇,Spinner每次只顯示使用者選中的元素。為Spinner載入資料的兩種方式:

  • 方式1:在XML檔案中先定義好要載入的資料資源,然後使用ArrayAdapter.createFromResource()把資源載入進來
  • 方式2:直接在Java程式碼中使用ArrayAdapter物件,把List中的資料資源載入到Spinner中,進行事件監聽——onItemSelectedListener,傳入一個實現了Spinner.onItemSelectedListener介面的匿名內部類物件,同時實現介面的onItemSelected方法,通過傳入的position引數完成匹配

在res/values/values.xml檔案中準備一個資料來源:

<string-array name = "corse_array">
    <item>Web程式設計</item>
    <item>Android引用開發</item>
    <item>大資料處理</item>
    <item>作業系統</item>
    <item>計算機網路</item>
    <item>作業系統</item>
    <item>資料結構</item>
    <item>C語言</item>
</string-array>

在Activity中,宣告初始化Spinner控制元件,繫結介面卡,實現資料監聽:

//宣告Spinner控制元件
private Spinner spinner;
spinner = (Spinner) findViewById(R.id.spinner1);
//將可選內容與ArrayAdapter連線起來
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.courses, android.R.layout.simple_spinner_item);
//設定下拉選單的風格
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//將adapter 新增到spinner中
spinner.setAdapter(adapter);
spinner.setPrompt("請選擇課程");
spinner.setSelection(0, true);
//新增事件Spinner事件監聽
spinner.setOnItemSelectedListener(……)

案例:

介面程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="聯想輸入" />

        <AutoCompleteTextView
            android:id="@+id/autoCompleteTextView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10" >

            <requestFocus />
        </AutoCompleteTextView>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="請選擇你最喜歡的專業課" />

        <Spinner
            android:id="@+id/spinner1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

</LinearLayout>

執行程式碼:

public class AdapterViewActivity extends Activity{

    private AutoCompleteTextView autoText;
    private Spinner spinner;
    String[] contents = new String[]{"Student","Student1", "student2","AAA","ST1","duts","學生","User", "tv","Study","study","yyy"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.adapter_view_layout);
        initView();
    }

    private void initView() {
        autoText = (AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
        ArrayAdapter<String> adapter1 = new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, contents);

        //將adapter1 新增到AutoCompleteTextView中
        autoText.setAdapter(adapter1);
        autoText.setTextColor(Color.BLACK);
        //設定輸入2個字元後開始提示
        autoText.setThreshold(2);

        spinner = (Spinner) findViewById(R.id.spinner1);
        //將可選內容與ArrayAdapter連線起來
        final ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this, R.array.corse_array, android.R.layout.simple_spinner_item);
        //設定下拉選單的風格
        adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        //將adapter2 新增到spinner中
        spinner.setAdapter(adapter2);

        spinner.setPrompt("請選擇課程");
        spinner.setSelection(0, true);
        //新增事件Spinner事件監聽
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String choice = getResources().getStringArray(R.array.corse_array)[position];
                Toast.makeText(AdapterViewActivity.this,
                        "你選的是"+choice, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

    }
}

在這裡插入圖片描述

在這裡插入圖片描述

ListView

ListView以列表形式展示內容,並根據資料的長度自適應顯示。採用MVC模式將前端顯示與後端資料分離,提供數
據的List或陣列相當於Model,listView相當於檢視,Adapter相當於Control,將資料適配到控制元件中。

使用步驟:

  • 1.宣告並初始化ListView控制元件。可以讓Activity直接繼承ListActivity或在Activity佈局中加入ListView控制元件,在Activity中進行宣告或初始化。
  • 2.構造Adapter物件,通過Adapter獲取要顯示的資料
  • 3.繫結Adapter,通過setAdapter()將ListView和Adapter繫結。
  • 4.監聽ListView,列表的響應事件。(單擊或長按)

響應使用者單機事件:
setOnItemClickListener()繫結AdapterView.OnItemClickListener介面,實現onItemClick方法,在其中進行單擊事件處理list.setOnItemClickListener(new AdapterView.OnItemClickListener(){……}})

  • parent:發生單擊動作的ListView物件
  • view:在ListView中被單擊的View
  • position:點選項在ListView中的位置
  • id:點選項的行id

響應使用者長按事件:
setOnItemLongClickListener()繫結AdapterView.OnItemLongClickListener介面,實現onItemLongClick方法,在其中進行長按事件處理:list.setOnLongItemClickListener(new AdapterView.OnItemLongClickListener(){……})

  • parent:發生單擊動作的ListView物件
  • view:在ListView中被長按的View
  • position:被長按的列表項在ListView中的位置
  • id:被長按的列表項的行id

使用Adapter物件給ListView填充資料

Adapter介面卡: Adapter物件在Adapter控制元件和資料來源之間扮演橋樑的角色。提供訪問資料來源的入口,把從資料來源拿到的資料項逐項載入到Adapter控制元件中。四種Adapter介面卡:

  • ArrayAdapter:適用於列表項只含有文字資訊的情況
  • SimpleAdapter:適用於每一個列表項中含有不同的子控制元件,比如圖片+文字+按鈕的
  • SimpleCursorAdapter:專門用來把一個Cursor中的資料對映到列表中,Cursor中的每一條資料對映為列表中的一項
  • 自定義Adapter:繼承BaseAdapter,完全自定義資料適配方式,靈活性最強

ArrayAdapter

  • 資料來源:陣列 || List
  • 方法:ArrayAdapter adapter = new ArrayAdapter(this, R.layout.array_item_1, dataList);
    listView.setAdapter(adapter);
  • 屬性說明:
    Context context:Context上下文物件
    int resource:對應列表項item的佈局檔案
    int textViewResourceId:列表item佈局中對應的TextView的ID
    Object[] object:需要顯示資料的集合
    List object:需要顯示資料的集合

案例:

佈局程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/array_listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:dividerHeight="3dp" />

</LinearLayout>

執行程式碼:

public class ArrayAdapterListActivity extends Activity {

    private ListView listView;
    private List<String> dataList;
    private ArrayAdapter<String> adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.array_listview_layout);
        listView = (ListView) findViewById(R.id.array_listview);
        dataList = new ArrayList<String>();
        for (int i = 0; i <=50; i++) {
            dataList.add("ListView 測試文字,第"+(i+1)+"項");
        }
        adapter = new ArrayAdapter<String>(this, R.layout.array_adapter_item, dataList);
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(ArrayAdapterListActivity.this, "你點選的是"+(position+1)+"項",
                        Toast.LENGTH_SHORT).show();
            }
        });

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                final int myPosition = position;
                new AlertDialog.Builder(ArrayAdapterListActivity.this)
                        .setIcon(R.mipmap.ic_launcher)
                        .setTitle("警告")
                        .setMessage("你確定要刪除嗎?")
                        .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dataList.remove(myPosition);
                                adapter.notifyDataSetChanged();
                            }
                        })
                        .setNegativeButton("取消", null)
                        .create().show();

                return true;
            }
        });
    }
}

執行結果:
在這裡插入圖片描述
在這裡插入圖片描述

SimpleAdapter
使用SimpleAdapter豐富Item中的元件,
資料來源:List<Map<String,Object>>,一個Map對應一個列表項,列表項佈局在/res/layout/中定義
實質:使用Map的資料反覆填充XML佈局檔案的各個控制元件的過程
缺點:附帶事件的元件(Button、CheckBox)無法將資料對映在ListView上

案例:

佈局程式碼:

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

    <ImageView
        android:id="@+id/simple_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="5dp"
        android:gravity="center_vertical"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/simple_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView"
            android:textSize="20sp" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="right" >

        <CheckBox
            android:id="@+id/simple_cbx"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:focusableInTouchMode="false" />

        <Button
            android:id="@+id/simple_btn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:text="詳情" />

    </LinearLayout>

</LinearLayout>

執行程式碼:

public class SimpleAdapterListActivity extends Activity {

    private List<HashMap<String, Object>> dataList;
    private SimpleAdapter adapter;
    private ListView simpleList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.array_listview_layout);

        dataList = new ArrayList<HashMap<String,Object>>();
        HashMap<String, Object> map;
        for (int i = 0; i < 50; i++) {
            map = new HashMap<String, Object>();
            map.put("img", R.mipmap.ic_launcher);
            map.put("text", "第"+(i+1)+"個測試文字");
            map.put("cbx", "");
            map.put("btn", "詳情");
            dataList.add(map);
        }
        /*
         *引數說明:
         * Context context:Context上下文
         * List<? extends Map <String,?>>:資料集合,用於儲存列表要顯示的資料
         * intresource:item列表項佈局檔案的id
         * from:一個String陣列,對應的Map上的每一個<key,value>的key值
         * to:int陣列,resource自定義佈局中各個控制元件的id,需要與from對應
         */
        adapter = new SimpleAdapter(this, dataList,R.layout.simple_list_item_layout,
                new String[]{"img","text","cbx","btn"},
                new int[]{R.id.simple_image,R.id.simple_text,R.id.simple_cbx,R.id.simple_btn});

        simpleList = (ListView) findViewById(R.id.array_listview);
        simpleList.setAdapter(adapter);

        simpleList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(SimpleAdapterListActivity.this, "你點選的是"+(position+1)+"項", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

執行結果:
在這裡插入圖片描述

自定義介面卡:
BaseAdapter是一個抽象類,使用該類使用者可以自定義介面卡,需要過載四個方法。

使用自定義介面卡可以豐富每一個Item的顯示效果,如交替背景色、便捷的事件監聽、自定義Item佈局、交替顯示背景色、為Button新增事件監聽

自定義Adapter繼承自BaseAdapter實現方法:

  • int getCount():獲得專案item數量
  • Object getItem(int position):或等當前選項
  • long getItemId(int position):獲得當前選項的id
  • abstract getView(int position,View converView,ViewGroup parent):返回列表對應的檢視

案例:

佈局檔案-好友列表:friend_list_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:gravity="center_vertical|center_horizontal" >

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/tangseng" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="25sp"
            android:text="我的好友" />

    </LinearLayout>

    <ListView
        android:id="@+id/friendlist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:dividerHeight="3dp" >
    </ListView>

</LinearLayout>

佈局檔案-列表設計:friend_list_item_layout.xml

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

    <ImageView
        android:id="@+id/iv_friend"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:layout_weight="3"
        android:scaleType="centerInside"
        android:src="@mipmap/tangseng" />

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="6"
        android:layout_marginLeft="5dp"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/tv_friend_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="TextView" />

        <TextView
            android:id="@+id/tv_friend_msg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="3"
        android:gravity="right" >

        <CheckBox
            android:id="@+id/cbx_friend"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:focusableInTouchMode="false"/>

        <Button
            android:id="@+id/btn_friend_detail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:text="詳情" />

    </LinearLayout>

</LinearLayout>

列表中有按鈕、核取方塊等元件,通常這些元件會自動獲取列表項的焦點,使得ListView列表項無法響應點選長按等事件。可通過設定android:focusable = “false”,以及android:focusableInTouchMode="false"來解決。

為了使Button、CheckBox等元件附帶的事件能夠對映到ListView上,或者豐富每一個Item的顯示效果,我們可以在自定義介面卡裡來操作:

public class MyAdapter extends BaseAdapter{

    private Context context;//執行上下文
    private List<Map<String, Object>> listItems;//好友資訊集合
    private LayoutInflater listContainer;//檢視容器
    //用於儲存CheckBox選中狀態
    public  Map<Integer,Boolean> cbxFlag = null;


    public class ViewHolder{
        //自定義控制元件集合
        public ImageView image;
        public TextView name;
        public TextView msg;
        public CheckBox cbx;
        public Button detail;
    }

    public MyAdapter(Context context, List<Map<String, Object>> listItems) {
        this.context = context;
        listContainer = LayoutInflater.from(context);
        this.listItems = listItems;
        cbxFlag = new HashMap<Integer, Boolean>();
        init();

    }

    private void init() {
        for (int i = 0; i < listItems.size(); i++) {
            cbxFlag.put(i, false);
        }
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public boolean hasChecked(int position) {
        return cbxFlag.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final int selectId = position;
        ViewHolder holder = null;

        if (convertView == null) {
            holder = new ViewHolder();
            //獲取list_item佈局檔案的檢視
            convertView = listContainer.inflate(R.layout.friend_list_item_layout, null);
            //獲取控制元件物件
            holder.image = (ImageView) convertView.findViewById(R.id.iv_friend);
            holder.name = (TextView) convertView.findViewById(R.id.tv_friend_name);
            holder.msg = (TextView) convertView.findViewById(R.id.tv_friend_msg);
            holder.cbx = (CheckBox) convertView.findViewById(R.id.cbx_friend);
            holder.detail = (Button) convertView.findViewById(R.id.btn_friend_detail);
            //設定控制元件集到convertView
            convertView.setTag(holder);

        }else {
            holder = (ViewHolder) convertView.getTag();
        }

        //設定顏色交替
        if (position%2 ==0) {
            convertView.setBackgroundColor(Color.parseColor("#CAFFFF"));
        } else {
            convertView.setBackgroundColor(Color.parseColor("#B3FAFAFA"));
        }

        holder.image.setImageResource((Integer) listItems.get(position).get("image"));
        holder.name.setText((String) listItems.get(position).get("name"));
        holder.msg.setText((String) listItems.get(position).get("msg"));

        holder.detail.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AlertDialog.Builder(context)
                        .setIcon((Integer) listItems.get(selectId).get("image"))
                        .setTitle((String) listItems.get(selectId).get("name"))
                        .setMessage((String) listItems.get(selectId).get("info"))
                        .setPositiveButton("確定", null)
                        .create()
                        .show();
            }
        });
        holder.cbx.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    cbxFlag.put(selectId, true);
                } else {
                    cbxFlag.put(selectId, false);
                }
            }
        });
        holder.cbx.setChecked(cbxFlag.get(selectId));
        return convertView;
    }
}

執行結果:


public class FriendListActivity extends Activity{

    private ListView listView;
    private MyAdapter listAdapter;
    private List<Map<String, Object>> listItems;

    private Integer[] imageIDs = {R.mipmap.lufei,R.mipmap.suolong,
            R.mipmap.wusuopu,R.mipmap.shanzhi,R.mipmap.namei,
            R.mipmap.qiaoba,R.mipmap.luobin,R.mipmap.fulanqi,R.mipmap.buluke,R.mipmap.xiangkesi,R.mipmap.baihuzi};

    private String[] friendNames = {"路飛", "索隆",
            "烏索普", "山治", "娜美", "喬巴","羅賓","弗蘭奇","布魯克","香克斯","白鬍子"};

    private String[] msgs = {"【船長】蒙奇·D·路飛(蒙奇·D·路飛 )","【劍士】羅羅諾亞·索隆","【狙擊手】烏索普",
            "【廚師】香吉士","【航海士】娜美","【船醫】託尼託尼·喬巴 ","【考古學家】妮可·羅賓 ","【船匠】弗蘭奇","【音樂家】布魯克","【四皇】香克斯","【四皇】白鬍子 "};

    private String[] infos = {"我是要當海賊王的男人"," 我總有一天要砍了那小子 ","我得了一上島就會死的病…… ",
            " 啊,娜美桑~羅賓醬~ ","財寶?!","笨蛋,就算你誇我bai我也不du會高興的~笨zhi蛋~笨蛋~ ","~_~"," 變態?是在叫我嗎? ","這位美麗的小姐,可以讓我欣賞一下你的內褲嗎?","這次還請給我一個面子","做我的兒子吧"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.friend_list_layout);

        listView = (ListView) findViewById(R.id.friendlist);
        listItems = getFriendItems();
        listAdapter = new MyAdapter(this, listItems);
        listView.setAdapter(listAdapter);

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (listAdapter.hasChecked(position)) {
                    Toast.makeText(FriendListActivity.this, "你想和" + listItems.get(position).get("name")
                                    + "冒險哇!", Toast.LENGTH_SHORT).show();
                }else {
                    Toast.makeText(FriendListActivity.this, "你想成為海賊王嗎?" , Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    private List<Map<String,Object>> getFriendItems() {
        List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
        for(int i = 0; i < friendNames.length; i++) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("image", imageIDs[i]);  //圖片資源
            map.put("name", friendNames[i]);  //好友名稱
            map.put("msg", msgs[i]); //最新訊息
            map.put("info", infos[i]);
            listItems.add(map);
        }
        return listItems;
    }
}

執行結果:
在這裡插入圖片描述

ListView快取原理及優化

  • 有多少行資料就需要繪製多少行Item,findViewById執行多次,極大地消耗了系統資源
  • 當啟動Activity呈現第一屏ListView的時候,convertView為零、convertView相當於一個快取,開始為0,當有條目變為不可見,它快取了它的資料,後面再出來的條目只需要更新資料就可以了,這樣大大節省了系統資料的開銷。
  • 利用convertView實現快取,條目不可見時,快取資料,新的條目使用已經例項化的元件
    ViewHolder
    setTag(holder) 為每個View繫結一個存放控制元件的ViewHolder物件
    getTag() 避免了findViewById對控制元件的層層查詢,而是快速定位到控制元件
    使用ConvertView實現快取,改程式序

GridView

ListView適用列表是單列多行的形式,如果列表是多行多列的網狀形式,則可以考慮使用GridView:
常用屬性:

  • android:numColumns 設定列數,auto_fit將列數設定為自動
  • android:columnWidth 設定每列的寬度,也就是item的寬度
  • android:gravity 設定每個網路的比重位置,可選的值有:top、bottom、left、right、center…多個時使用|分開
  • android:stretchMode 縮放模式,設定列應該以何種形式填充可用空間
  • android:horizontalSpacing 網格之間列的預設水平距離
  • android:verticalSpacing 設定網格間的預設垂直距離

案例:

佈局介面:grid_view_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <GridView
        android:id="@+id/grid_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:numColumns="3"
        android:horizontalSpacing="10dp"
        android:verticalSpacing="10dp"/>
</LinearLayout>

每個模組的樣式:grid_view_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/gridItemImage"
        android:layout_height="100dp"
        android:layout_width="wrap_content"
        android:layout_centerHorizontal="true">
    </ImageView>

    <TextView
        android:id="@+id/gridItemText"
        android:layout_width="wrap_content"
        android:layout_below="@+id/gridItemImage"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:layout_centerHorizontal="true">
    </TextView>

    <TextView
        android:id="@+id/gridItemPriceText"
        android:layout_width="wrap_content"
        android:layout_below="@+id/gridItemText"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:layout_centerHorizontal="true">
    </TextView>

</RelativeLayout>

執行程式碼:


public class GridViewActivity extends Activity {

    private GridView imageGridView;
    private int[] Card={R.mipmap.lufei, R.mipmap.suolong,
            R.mipmap.wusuopu, R.mipmap.suolong, R.mipmap.namei,
            R.mipmap.qiaoba,R.mipmap.luobin,R.mipmap.fulanqi,
            R.mipmap.baihuzi,R.mipmap.xiangkesi,R.mipmap.baihuzi};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.grid_view_layout);

        imageGridView = (GridView) findViewById(R.id.grid_view);
        final List<HashMap<String, Object>> mapsList = new ArrayList<HashMap<String, Object>>();
        for (int i = 0; i < 60; i++) {
            HashMap<String, Object> hashMap = new HashMap<String, Object>();
            hashMap.put("Image", Card[(int)(Math.random()*11)]);
            hashMap.put("text", "人物卡牌"+i);
            hashMap.put("pro", "售價"+(int)(Math.random()*10000000)+"¥");
            mapsList.add(hashMap);
        }
        SimpleAdapter adapter = new SimpleAdapter(getApplicationContext(),
                mapsList, R.layout.grid_view_item_layout, new String[] {
                "Image", "text","pro" }, new int[] {R.id.gridItemImage , R.id.gridItemText , R.id.gridItemPriceText});
        imageGridView.setAdapter(adapter);

        imageGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(GridViewActivity.this,"你選的是"+mapsList.get(position).get("text"),Toast.LENGTH_SHORT).show();
            }
        });
    }
}

執行結果:

在這裡插入圖片描述

相關文章