在android中使用listview時須要瞭解listview加載數據的原理,爲了不listview因爲列表項過多每次須要進行new形成性能低下的問題,android中的listview使用了控件複用從而避免了每次進行new控件的問題。java
@Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder viewHolder = null; if(convertView==null) { viewHolder = new ViewHolder(); view = getLayoutInflater().inflate(R.layout.list_item, null); viewHolder.btn = (Button)view.findViewById(R.id.buttonid); viewHolder.textView = (TextView)view.findViewById(R.id.textid); viewHolder.radioBtn = (CheckBox)view.findViewById(R.id.radioid); view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder)view.getTag(); }
自定義adapter時重寫getView方法時只有當converView爲空時才須要建立控件,只須要建立屏幕上恰好能夠放下的那幾條控件便可。android
在listview item上使用checkbox等空間時須要注意的問題是,checkbox選中的狀態會錯亂,如選中了第一條數據當滾動列表時該選中的狀態可能會跑到其餘條目上去,這個問題就是listview複用形成的。ide
目前該問題的解決我是經過,將選中的checkbox id放入hashmap中,佈局
Map<Integer, Boolean> isCheckMap = new HashMap<Integer, Boolean>();
當滾動listview時判斷該條目位置是否在這個hashmap中,若是在表示以前選中了,若是不在表示未選中將checkbox狀態設爲false。post
//找到須要選中的條目 if(isCheckMap!=null && isCheckMap.containsKey(position)) { viewHolder.checkBtn.setChecked(isCheckMap.get(position)); } else { viewHolder.checkBtn.setChecked(false); }
爲了獲取到checkbox的選中事件,還須要實現checkbox的setOnCheckedChangeListener性能
viewHolder.checkBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int radiaoId = Integer.parseInt(buttonView.getTag().toString()); if(isChecked) { //將選中的放入hashmap中 isCheckMap.put(radiaoId, isChecked); } else { //取消選中的則剔除 isCheckMap.remove(radiaoId); } } });
另外須要注意的一個問題是,因爲列表項佈局文件使用了checkbox,Button等控件,若是不作設置的話這些控件的監聽事件會優先於listview的setOnItemClickListener事件響應,因此即便listview實現了這個監聽,在點擊item的時候也捕獲不到事件。解決辦法以下:spa
<?xml version="1.0" encoding="utf-8"?> <!-- android:descendantFocusability="blocksDescendants"表示覆蓋子空間獲取焦點,解決itemclick無效的問題--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:orientation="horizontal" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/imageid" style="@style/baseLayout" android:layout_alignParentLeft="true" android:background="@drawable/sym_keyboard_delete" /> <TextView android:id="@+id/textid" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginLeft="10dp" android:layout_toLeftOf="@+id/radioid" android:text="sdfa" /> <CheckBox style="@style/baseLayout" android:id="@+id/radioid" android:layout_height="50dp" android:layout_toLeftOf="@+id/buttonid" /> <Button style="@style/baseLayout" android:layout_height="50dp" android:id="@+id/buttonid" android:layout_alignParentRight="true" android:background="@drawable/sym_keyboard_done" /> </RelativeLayout> </LinearLayout>
在listview item佈局頁面的根位置添加android:descendantFocusability="blocksDescendants" 表示覆蓋子控件獲取焦點,解決itemclick無效的問題。.net
完整的代碼以下:code
Activity類xml
package com.example.sf; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.annotation.SuppressLint; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ListView; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; public class listViewActivity extends BaseActivity{ private ListView listView; private List<HashMap<String, Object>> listData; private Handler handler = null; Map<Integer, Boolean> isCheckMap = new HashMap<Integer, Boolean>(); final List<HashMap<String, Integer>> isCheckList = new ArrayList<HashMap<String, Integer>>(); @Override public int getContentViewId() { return R.layout.list_main; } @Override public void init() { handler = new Handler(); listView = (ListView)findViewById(R.id.listid); listData = getData(); listView.setAdapter(new myAdapter()); listView.setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { Log.e("scrollState",scrollState+""); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if(firstVisibleItem+visibleItemCount<totalItemCount)//判斷是否須要加載數據 { new Thread(new Runnable() { @Override public void run() { handler.postDelayed(new Runnable() { @Override public void run() { } },10); } }).start(); } } }); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view,int position, long id) { Toast.makeText(getApplicationContext(), view.getTag()+"", Toast.LENGTH_SHORT).show(); } }); } /** * 數據封裝 * @return */ private List<HashMap<String, Object>> getData() { List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>(); for(int i=0;i<20;i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("radioid", i); map.put("textview", "本元素的上邊緣"+i); list.add(map); } return list; } /** * 自定義Adapter * @author Administrator * */ public class myAdapter extends BaseAdapter { @Override public int getCount() { return listData.size(); } @Override public Object getItem(int position) { return listData.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; ViewHolder viewHolder = null; if(convertView==null) { viewHolder = new ViewHolder(); view = getLayoutInflater().inflate(R.layout.list_item, null); viewHolder.btn = (Button)view.findViewById(R.id.buttonid); viewHolder.textView = (TextView)view.findViewById(R.id.textid); viewHolder.checkBtn = (CheckBox)view.findViewById(R.id.radioid); view.setTag(viewHolder); } else { view = convertView; viewHolder = (ViewHolder)view.getTag(); } viewHolder.textView.setText(listData.get(position).get("textview").toString()); viewHolder.checkBtn.setTag(listData.get(position).get("radioid").toString()); //找到須要選中的條目 if(isCheckMap!=null && isCheckMap.containsKey(position)) { viewHolder.checkBtn.setChecked(isCheckMap.get(position)); } else { viewHolder.checkBtn.setChecked(false); } viewHolder.btn.setTag(listData.get(position).get("radioid").toString()); viewHolder.btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "點擊了"+v.getTag(), Toast.LENGTH_LONG).show(); } }); viewHolder.checkBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { int radiaoId = Integer.parseInt(buttonView.getTag().toString()); if(isChecked) { //將選中的放入hashmap中 isCheckMap.put(radiaoId, isChecked); } else { //取消選中的則剔除 isCheckMap.remove(radiaoId); } } }); return view; } } public class ViewHolder { private TextView textView; private CheckBox checkBtn; private Button btn; } }
listview item佈局文件
<?xml version="1.0" encoding="utf-8"?> <!-- android:descendantFocusability="blocksDescendants"表示覆蓋子空間獲取焦點,解決itemclick無效的問題--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:descendantFocusability="blocksDescendants" android:orientation="horizontal" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/imageid" style="@style/baseLayout" android:layout_alignParentLeft="true" android:background="@drawable/sym_keyboard_delete" /> <TextView android:id="@+id/textid" android:layout_width="wrap_content" android:layout_height="50dp" android:layout_marginLeft="10dp" android:layout_toLeftOf="@+id/radioid" android:text="sdfa" /> <CheckBox style="@style/baseLayout" android:id="@+id/radioid" android:layout_height="50dp" android:layout_toLeftOf="@+id/buttonid" /> <Button style="@style/baseLayout" android:layout_height="50dp" android:id="@+id/buttonid" android:layout_alignParentRight="true" android:background="@drawable/sym_keyboard_done" /> </RelativeLayout> </LinearLayout>
源碼下載位置:
http://download.csdn.net/detail/linchengbiao123/7133959