Andorid 開發中咱們經常會用到listview這個控件,而listview中如何獲取到子item的控件並設置相應事件則相對複雜,而且自定義listview經常須要自定義適配器等等,下面這篇文章將主要介紹如何獲取item控件並設置響應事件,主要實現如何點擊listview子item中的一個按鈕跳轉到下一個Activity。廢話很少說直接上代碼:java
package com.example.demo_listitem; import java.util.ArrayList; import java.util.HashMap; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends Activity { private ListView list; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_listview); list=(ListView) findViewById(R.id.listView1)**//找到Listview控件** Cadapter ca=new Cadapter(this);**//獲得一個Cadapter對象(自定義適配器)** list.setAdapter(ca);**//爲listview綁定適配器** } **//定義一個獲得數據的方法** public ArrayList<HashMap<String, Object>> getData() { ArrayList<HashMap<String, Object>> listitem=new ArrayList<HashMap<String, Object>>();**//動態數組,裝數據** for(int i=0;i<20;i++) { **//利用散列映射添加簡單數據** HashMap<String, Object> map=new HashMap<String,Object>(); map.put("title", "hello world"); listitem.add(map); } return listitem;**//返回數據源** } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
最重要的地方,自定義適配器:Cadatper(繼承自BaseAdapter)
(PS:使用BaseAdapter必須寫一個類繼承它,同時BaseAdapter是一個抽象類,繼承它必須實現它的方法。而最重要的方法就是getView()方法,在此方法內item的繪製(核心的核心),item內控件的尋找,事件的設定都能作。當開始繪製listview時,首先會調用其getCount()方法,獲得listview的長度,而後根據這個長度來繪製listview的每個item)android
package com.example.demo_listitem; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView.FindListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class Cadapter extends BaseAdapter{ private Context context1; private LayoutInflater mInflater; public Cadapter(Context context) { context1=context;**//將當前頁面的對象賦給context1** this.mInflater=LayoutInflater.from(context1); } @Override public int getCount() { MainActivity m=new MainActivity(); return m.getData().size();**//返回listview長度** } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView==null) { **//繪製子item** convertView=mInflater.inflate(R.layout.activity_listitem, null); **//獲得各個控件** holder=new ViewHolder();**//存放控件的對象** holder.tv=(TextView) convertView.findViewById(R.id.textView1); holder.bt=(Button) convertView.findViewById(R.id.button1); convertView.setTag(holder); **//將數據和convertView綁定在一塊兒** } else { holder=(ViewHolder) convertView.getTag(); } MainActivity m=new MainActivity(); holder.tv.setText(m.getData().get(position).get("title").toString());**//爲item中的Textview設置數據** **//按鈕的點擊事件** holder.bt.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent=new Intent(context1,NextActivity.class); context1.startActivity(intent); } }); return convertView; } }
(getview中的代碼,其實徹底能夠不用convertView以及holder,直接加入item佈局和設計相應的組件屬性就好了,這樣作雖然行得通,但只適用於listview中item個數較少的時候可行,當item個數達到1000,10000,1000000就行不通了,由於每一個item系統都會繪製一次(getView()一次),item個數較少時還好,當大量的item須要繪製時,會耗費大量的資源在繪製上,這顯然實不可取的。
因此,以上代碼是通過優化過的,優化之處在於使用convertView和ViewHolder的使用,convertViewconvertView至關於一個緩存,當滑動時,有的條目變爲不可見,它緩存了此條目的數據,後面再出來的條目只須要更新數據就能夠了,這樣大大節省了系統資料的開銷
而ViewHolder也是對listview的進一步優化,將holder(找到的控件)用setTag綁定到convertView上,用的時候再用getTag()取出,不用每次都去findviewById,節約系統開銷)web
package com.example.deo_listitem; import android.app.Activity; import android.os.Bundle; public class NextActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_next); } }
package com.example.demo_listitem; import android.widget.Button; import android.widget.TextView; public final class ViewHolder { public TextView tv; public Button bt; }
<?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" > <ListView android:id="@+id/listView1" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>
<?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" android:weightSum="1" > <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:orientation="vertical" android:background="#ddc200" android:weightSum="1" > <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:orientation="vertical" android:layout_weight="0.5" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Medium Text" android:textAppearance="?android:attr/textAppearanceMedium" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="0.5" android:orientation="vertical" > <Button android:id="@+id/button1" style="?android:attr/buttonStyleSmall" android:layout_width="112dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="下一頁" /> </LinearLayout> </LinearLayout> </LinearLayout>
<?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" android:background="#ddc200" > </LinearLayout>
convertView原理:當初始顯示一屏listview時,convertView的值爲空,(由於沒有舊的item,舊的指:滑動時移出屏幕的item),當屏幕移動時,有的item滑到屏幕外面,成了舊的item,convertView會回收這些成爲舊了的item並緩存起來,若是有新的item產生,則getview()中的convertView就不是空的,而是移出屏幕的item的值(舊item),咱們須要作的就是將須要顯示的數據填充進去就好了,也就是說convertView至關於一個緩存,當有條目變爲不可見,它緩存了它的數據,後面再出來的條目只須要更新數據就能夠了,這樣大大節省了系統資料的開銷。數組