1. 程式人生 > >Android-UI開發之Adapter及Adapter控制元件

Android-UI開發之Adapter及Adapter控制元件

一.Adapter的概述

  • ArrayAdapter
  • SimpleAdapter
  • SimpleCursorAdapter
  • BaseAdapter及自定義Adapter
  • Adapter控制元件

1.Adapter介面卡

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

2.四種Adapter介面卡

  • ArrayAdapter
  • SimpleAdapter
  • SimpleCursorAdapter
  • 自定義的Adapter(繼承自BaseAdapter)

二.AutoCompleteTextView控制元件

1.AutoCompleteTextView概述

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

2.例子一

這裡寫圖片描述

public class MainActivity extends Activity {

    private AutoCompleteTextView autoCompleteTextView;

    String[] contents = new String[]{"China","China1"
, "china2","USA","USA1","USA2","唱歌","china", "cd","ch","chi","chin"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void
initView() { autoCompleteTextView=(AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1); ArrayAdapter<String> arrayAdapter=new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,contents); autoCompleteTextView.setAdapter(arrayAdapter); autoCompleteTextView.setThreshold(2);//輸入一個字母就開始自動提示,這裡是設定輸出第幾個才提示 } }

三.Spinner控制元件

1.Spinner控制元件概述

  • Spinner下拉列表,外觀是一個一行的列表框,使用者單擊控制元件,下拉出選項列表供使用者選擇
  • Spinner每次只顯示使用者選中的元素

  • 為Spinner載入資料的兩種方式

    • 方式1:在XML檔案中先定義好要載入的資料資源,然後使用ArrayAdapter.createFromResource()把資源載入進來
    • 方式2:直接在Java程式碼中使用ArrayAdapter物件,把List<T>中的資料資源載入到Spinner中
  • 事件監聽——onItemSelectedListener

    • 使用setOnItemSelectedListener()方法設定監聽,傳入一個實現了Spinner.onItemSelectedListener介面的匿名內部類物件,同時實現介面的onItemSelected方法,通過傳入的position引數完成匹配

2.例子一

這裡寫圖片描述

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name = "corse_array">
        <item>Android應用開發</item>
        <item>Java程式設計</item>
        <item>Java Web應用開發</item>
        <item>Html5應用開發</item>
        <item>軟體專案管理</item>
    </string-array>

</resources>
public class MainActivity extends Activity {

    private Spinner spinner;


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

    private void initView() {

        spinner=(Spinner) findViewById(R.id.spinner1);

        //將可選內容與ArrayAdapter連線起來

        final ArrayAdapter<CharSequence> adapter1=ArrayAdapter.createFromResource(MainActivity.this,R.array.corse_array,android.R.layout.simple_spinner_item);

        //設定下拉列表的風格
        adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        spinner.setAdapter(adapter1);

        spinner.setPrompt("請選擇課程");//標題

        spinner.setSelection(0,true);//設定預設

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> arg0, View arg1,
                    int position, long arg3) {
                // TODO Auto-generated method stub
                String choice = getResources().getStringArray(R.array.corse_array)[position];
                Toast.makeText(MainActivity.this,
                        "你選的是"+choice, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onNothingSelected(AdapterView<?> arg0) {
                // TODO Auto-generated method stub

            }
        });

    }



}

四.ListView控制元件

1.ListView控制元件概述

  • 以列表形式展示內容,並根據資料的長度自適應顯示
  • 繼承ListActivity或在Activity佈局中加入ListView控制元件
  • 採用MVC模式將前端顯示不後端資料分離

    • 提供資料的List或陣列相當於Model
    • ListView相當於檢視View
    • Adapter物件相當於Control
  • 指定Adapter物件,通過Adapter獲取要顯示的資料

2.為ListView填充資料

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

3.響應使用者事件

(1).響應使用者單擊事件

  • setOnItemClickListener()繫結
//AdapterView.OnItemClickListener介面,實現onItemClick方法,在其中進行單擊事件處理
list.setOnItemClickListener(new AdapterView.OnItemClickListener(){……}})
parent:發生單擊動作的ListView物件
view:在ListView中被單擊的View
position:點選項在ListView中的位置
id:點選項的行id

(2).響應使用者長按事件

  • setOnItemLongClickListener()繫結
//AdapterView.OnItemLongClickListener介面,實現onItemLongClick方法,在其中進行長按事件處理
list.setOnLongItemClickListener(new AdapterView.OnItemLongClickListener(){……})
parent:發生單擊動作的ListView物件
view:在ListView中被長按的View
position:被長按的列表項在ListView中的位置
id:被長按的列表項的行id

4.例子-ArrayAdapter

這裡寫圖片描述

public class MainActivity extends Activity {

    private ListView listView;

    private List<String> stringlist;

    private ArrayAdapter<String> adapter;   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {

        listView=(ListView) findViewById(R.id.listView1);

        stringlist=new ArrayList<String>();

        for(int i=1;i<=50;i++){
            stringlist.add("ListView 這個第"+i+"個文字");
        }

        adapter=new ArrayAdapter<String>(this,R.layout.array_adapter_item,stringlist);

        listView.setAdapter(adapter);

        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
                    long id) {
                final int pos=position;
                new AlertDialog.Builder(MainActivity.this)
                .setTitle("是否要刪除?")
                .setPositiveButton("確定",new OnClickListener() {

                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        stringlist.remove(pos);
                        adapter.notifyDataSetChanged();

                    }
                })
                .setNegativeButton("取消",null)
                .setIcon(R.drawable.ic_launcher)
                .create()
                .show();

                return true;
            }
        });

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                    long id) {



            }
        });
    }





}

5.例子-SimpleAdapter

這裡寫圖片描述

public class MainActivity extends Activity {

    private List<Map<String,Object>> stringlist;

    private ListView listView;

    private SimpleAdapter adapter;  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {

        listView=(ListView) findViewById(R.id.listView1);

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

        for(int i=1;i<=50;i++){
            Map<String,Object> map=new HashMap<String, Object>();
            map.put("img",R.drawable.ic_launcher);
            map.put("text","我的名字叫"+i);
            map.put("cbx", i);
            map.put("btn", i);
            stringlist.add(map);
        }

        adapter=new SimpleAdapter(MainActivity.this,stringlist,R.layout.simple_list_item,new String[] {"img","text","cbx","btn"}, 
                new int[]{R.id.simple_image,R.id.simple_text,R.id.simple_cbx,R.id.simple_btn});//R.layout.simple_list_item自己寫的 對於ListView每一個控制元件的風格

        listView.setAdapter(adapter);

    }

}

這裡寫圖片描述

  • SimpleAdapter的弊端
    • 附帶事件的元件(Button、CheckBox)無法將資料對映在ListView上
    • 繼承BaseAdapter,自定義介面卡實現事件監聽
    • 豐富每一個Item的顯示效果
    • 如交替背景色、便捷的事件監聽

6.自定義Adapter

(1).自定義Adapter步驟

  • 繼承自BaseAdapter
  • 實現方法
    • 構造方法(類似SimpleAdapter)
    • getCount
    • getItem
    • getItemId
    • getView
    • 新增事件監聽

(2).例子一

這裡寫圖片描述

public class MyAdapter extends BaseAdapter {//自定義Adapter要繼承BaseAdapter

    public List<Map<String,Object>> lists;//好友集合列表

    public Context context;//上下文物件

    public LayoutInflater layoutInflater;//檢視容器

    public MyAdapter(Context context,List<Map<String,Object>> lists) {
               this.context=context;
               layoutInflater=LayoutInflater.from(context);
               this.lists=lists;
    }
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return lists.size();//獲取長度
    }

    @Override
    public Object getItem(int arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public long getItemId(int arg0) {
        // TODO Auto-generated method stub
        return 0;
    }

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

        final int pos=position;
        ViewHolder holder=null;

        if(convertView==null){

            holder=new ViewHolder();
            //獲取list_item佈局檔案的檢視
            convertView=layoutInflater.inflate(R.layout.friend_list_item,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.detail=(Button) convertView.findViewById(R.id.btn_friend_detail);
            //設定控制元件集到convertView
            convertView.setTag(holder);

        }else{

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

        holder.image.setImageResource((Integer)lists.get(position).get("image"));
        holder.name.setText((String) lists.get(position).get("name"));
        holder.msg.setText((String) lists.get(position).get("msg"));
        holder.detail.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                new AlertDialog.Builder(context)
                    .setIcon((Integer) lists.get(pos).get("image"))
                    .setTitle((String) lists.get(pos).get("name"))
                    .setMessage((String) lists.get(pos).get("info"))
                    .setPositiveButton("確定", null)
                    .create()
                    .show();
            }
        });
        return convertView;
    }

    public class ViewHolder{
            public ImageView image;//圖片
            public TextView name;    //名字
            public TextView msg; //長段話
            public Button detail;//按鈕
    }

}
public class MainActivity extends Activity {

    private List<Map<String,Object>> stringlist;

    private ListView listView;

    private MyAdapter adapter;  

    private Integer[] imgeIDs = {R.drawable.baigujing,R.drawable.sunwukong,
            R.drawable.shaseng,R.drawable.shaseng,R.drawable.guanyin,
            R.drawable.baigujing,R.drawable.baigujing};

    private String[] friendNames = {"女兒國王", "孫悟空",   
            "豬八戒", "沙僧", "觀音姐姐", "白骨精","東海龍女"}; 

    private String[] msgs = {"御弟哥哥,你好哇","師傅,小心妖怪","師傅,咱歇一歇",
            "師傅,請喝水","你太墨跡了","吃你的肉可以長生?","你想幹啥?"};

    private String[] infos = {"相見難,別亦難,怎訴這胸中語萬千","孫悟空是我的大徒弟!","豬八戒就是一頭懶豬!",
            "沙悟淨是個聽話的好徒兒!","救苦救難觀世音菩薩","白骨精,一直想吃我的肉,可惜你沒後臺!","小龍女,你在幹啥?"};

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

    private void initView() {

        listView=(ListView) findViewById(R.id.friendlist);

        stringlist=getStringlist();

        adapter=new MyAdapter(this,stringlist);

        listView.setAdapter(adapter);

         listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
             @Override
             public boolean onItemLongClick(AdapterView<?> parent, View view, int position,
                     long id) {
                 final int pos=position;
                 new AlertDialog.Builder(MainActivity.this)
                 .setTitle("是否要刪除?")
                 .setPositiveButton("確定",new OnClickListener() {

                     @Override
                     public void onClick(DialogInterface arg0, int arg1) {
                         stringlist.remove(pos);
                         adapter.notifyDataSetChanged();

                     }
                 })
                 .setNegativeButton("取消",null)
                 .setIcon(R.drawable.ic_launcher)
                 .create()
                 .show();

                 return true;
             }
         });

         listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position,
                     long id) {



             }
         });
     }


    private List<Map<String, Object>> getStringlist() {
        stringlist=new ArrayList<Map<String,Object>>();

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





}

7.ListView快取原理及優化

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

END!!!!!!!!!!!