BaseAdapterjava
有時候,列表不光會用來作顯示用,咱們一樣能夠在在上面添加按鈕。添加按鈕首先要寫一個有按鈕的xml文件,而後天然會想到用上面的方法定義一個適配器,而後將數據映射到佈局文件上。可是事實並不是這樣,由於按鈕是沒法映射的,即便你成功的用佈局文件顯示出了按鈕(確實能夠顯示)也沒法添加按鈕的響應,這時就要研究一下ListView是如何現實的了,並且必需要重寫一個類繼承BaseAdapter。下面的示例將顯示一個按鈕和一個圖片,兩行字若是單擊按鈕將刪除此按鈕的所在行。並告訴你ListView到底是如何工做的。android
一。要達到的目的 架構
如上圖,在一個ListView 中加入各類數據 。且在點擊 button 和 item 時都 有反應,這裏,咱們就要用到 BaseAdapter(若是用SimpleAdapter ,沒法給Btn 加響應) ,並重寫它的方法了。ssh
首先是程序的總體架構。ide
(1)總體架構 函數
與ListView (1)中的相同 ,咱們用固定的架構 ,在這裏,咱們寫入部分方法。佈局
public class ListDemo extends Activity { private String [] names; //原始 數據 private String [] infos ; private int [] imgs; private List<Map<String ,Object>>listItems ; //MyAdapter要用的數據格式 private ListView lv ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listview); loadData(); //將原始數據轉化成MyAdapter 要的格式 initCtrl(); //完界面初始化與設置 lv.setOnItemClickListener(new OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id ) { // TODO Auto-generated method stub Toast.makeText(getBaseContext(), "chat with "+names[position], Toast.LENGTH_SHORT).show(); Intent iChat= new Intent(getBaseContext() ,Chat.class); startActivity(iChat); } }); } private void initCtrl() { // TODO Auto-generated method stub lv =(ListView)findViewById(R.id.listView1); MyAdapter adapter = new MyAdapter (getBaseContext() ,listItems); lv.setAdapter(adapter); } private List<Map<String, Object>> loadData() { // TODO Auto-generated method stub names =new String []{"阿今 ","hwj","twq","isshe"}; imgs = new int [] {R.drawable.a1,R.drawable.b ,R.drawable.c, R.drawable.d}; infos =new String [] {"1988","1992","1993","1994"}; listItems =new ArrayList<Map<String,Object>> (); //實例化 for (int i=0;i<names.length;i++){ Map<String ,Object> map = new HashMap<String ,Object>(); map.put("name", names[i]); map.put("info", infos[i]); map.put("img", imgs[i]); listItems.add(map); } return listItems; } }
重點與難點 在於 MyAdapter 的實現 。this
(2) item 的XML 文件 item.xmlspa
相似於這種佈局,用相對佈局最好實現 。注意,裏面爲了在加入 Button 後,Item 還能有響應,要取消Button 的焦點,咱們用的是code
android:focusable="false"
具體以下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/name" android:layout_below="@+id/name" android:layout_marginTop="16dp" android:text="info" android:textAppearance="?android:attr/textAppearanceMedium" /> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginLeft="20dp" android:layout_toRightOf="@+id/img" android:text="name" android:textAppearance="?android:attr/textAppearanceLarge" /> <ImageView android:id="@+id/img" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignBottom="@+id/info" android:layout_alignParentLeft="true" android:layout_marginLeft="15dp" android:src="@drawable/a" /> <Button android:id="@+id/btn" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_alignBottom="@+id/info" android:layout_alignParentRight="true" android:layout_marginRight="50dp" android:focusable="false" android:text="OK" /> </RelativeLayout>
(3) MyAdaper文件
重點在於重寫 getView方法,注意,在構造函數 中必定要有context ,不然在後面要用到時沒有辦法 ,好比下面中的 Button 監聽 器裏面的。
下面程序 中,知識 點有: LayoutInflater 的用法,getTag()的用法 ,等。之後用的時候 能夠參考 。
public class MyAdapter extends BaseAdapter { private Context context; private LayoutInflater inflater ; private List<Map<String ,Object>>listItems; private class ViewHolder{ ImageView img; TextView name; TextView info; Button btn; //控件 的聲明 都 在Holder裏面 } public MyAdapter(Context context, List<Map<String, Object>> listItems) { // TODO Auto-generated constructor stub this.listItems=listItems; this.context=context; inflater= LayoutInflater.from(context); //新建 一個擴展布局,Obtains the LayoutInflater from the given context. } @Override public int getCount() { // TODO Auto-generated method stub return listItems.size() ; } @Override public Object getItem(int position) { // TODO Auto-generated method stub return listItems.get(position); } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub System.out.println("getView " + position + " " + convertView); ViewHolder holder; /* * Recycler(反覆循環器):若是convertview 是第一次展現咱們就建立新的Holder對象與之綁定, * 並在最後經過return convertview 返回,去顯示;若是convertview * 是回收來的那麼咱們就沒必要建立新的holder對象,只須要把原來的綁定的holder取出加上新的數據就好了 */ if (convertView ==null){ convertView= inflater.inflate(R.layout.item, null); //實例化要擴展的佈局 holder= new ViewHolder(); holder.img= (ImageView) convertView.findViewById(R.id.img); holder.name=(TextView) convertView.findViewById(R.id.name); holder.info=(TextView) convertView.findViewById(R.id.info); holder.btn= (Button)convertView.findViewById(R.id.btn); convertView.setTag(holder); /*Sets the tag associated with this view. A tag can be used to mark * a view in its hierarchy and does not have to be unique within the hierarchy. * Tags can also be used to store data within a view without resorting to * another data structure. */ }else { holder=(ViewHolder) convertView.getTag(); //將holder 添加到動態生成的View裏面 } //數據的設置 holder.name.setText((CharSequence) listItems.get(position).get("name")); holder.info.setText((CharSequence) listItems.get(position).get("info")); holder.img.setImageResource((Integer) listItems.get(position).get("img")); holder.btn.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(context, "bnt clicked", Toast.LENGTH_SHORT).show(); } }); return convertView; } }