在android中使用listview时需要了解listview加载数据的原理,为了避免listview由于列表项过多每次需要进行new造成性能低下的问题,android中的listview使用了控件复用从而避免了每次进行new控件的问题。

@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为空时才需要创建控件,只需要创建屏幕上刚好可以放下的那几条控件即可。

在listview item上使用checkbox等空间时需要注意的问题是,checkbox选中的状态会错乱,如选中了第一条数据当滚动列表时该选中的状态可能会跑到其他条目上去,这个问题就是listview复用造成的。

目前该问题的解决我是通过,将选中的checkbox id放入hashmap中,

Map<Integer, Boolean> isCheckMap =  new HashMap<Integer, Boolean>();

当滚动listview时判断该条目位置是否在这个hashmap中,如果在表示之前选中了,如果不在表示未选中将checkbox状态设为false。

//找到需要选中的条目
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的时候也捕获不到事件。解决办法如下:

<?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无效的问题。

完整的代码如下:

Activity类

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

android listview 使用checkbox问题的更多相关文章

  1. [置顶] android ListView包含Checkbox滑动时状态改变

    题外话: 在xamarin android的开发中基本上所有人都会遇到这个小小的坎,的确有点麻烦,当时我也折腾了好一半天,如果你能看到这篇博客,说明你和我当初也是一样的焦灼,如果你想解决掉这个小小的坎 ...

  2. Android ListView带CheckBox实现单选

    第1种方法: 首先是我们的bean: public class Bean { private boolean isChecked; private String msg = "这是一条测试数 ...

  3. android ListView中CheckBox错位的解决

    貌似已经非常晚了,可是还是想记下笔记,想让今天完满. 在ListView中加了checkBox,但是发现点击改变其选中状态的时候,发现其位置错乱.状态改变的并非你选中的,百思不得其解.后面通过上网查资 ...

  4. Android在listview添加checkbox实现单选多选操作问题(转)

    转自:http://yangshen998.iteye.com/blog/1310183 在Android某些开发需求当中,有时候需要在listveiw中加入checkbox实现单选,多选操作.表面上 ...

  5. Android 长按Listview显示CheckBox,实现批量删除。

    ListView实现的列表,如果是可编辑,可删除的,一般都要提供批量删除功能,否则的话,一项一项的删除体验很不好,也给用户带来了很大的麻烦. 实现效果图 具体实现代码 select.xml 主布局文件 ...

  6. android UI进阶之实现listview中checkbox的多选与记录

    今天继续和大家分享涉及到listview的内容.在很多时候,我们会用到listview和checkbox配合来提供给用户一些选择操作.比如在一个 清单页面,我们需要记录用户勾选了哪些条目.这个的实现并 ...

  7. Android(java)学习笔记133:ListViewProject案例(ListView + BaseAdapter + CheckBox)

    这个案例可能稍微复杂一点,我会讲述详细一点: 1.首先是AndroidManifest.xml: <?xml version="1.0" encoding="utf ...

  8. Android ListView(Selector 背景图片 全选 Checkbox等按钮)

    list_item.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xm ...

  9. 【转】android UI进阶之实现listview中checkbox的多选与记录--不错

    原文网址:http://www.cnblogs.com/notice520/archive/2012/02/17/2355415.html 今天继续和大家分享涉及到listview的内容.在很多时候, ...

随机推荐

  1. MenuItem

    private void 文件ToolStripMenuItem_Click(object sender, EventArgs e) { MessageBox.Show("打开测试" ...

  2. 五、mysql存储引擎

    show variable like 'table_type'; 显示系统默认存储引擎 show engine\G 显示系统支持存储殷勤 =============================== ...

  3. 【学习总结】【多线程】 线程 & 进程 & NSThread(多线程的一套API)

    一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开 Chrome.Xcode,系统就会分别启动2个进 ...

  4. Unity3d本地存储

    原文地址:http://blog.csdn.net/dingkun520wy/article/details/49386507 (一)简单数据存储PlayerPrefs 这种存储方法比较简单直接上代码 ...

  5. 如何在windows下安装GIT

    如何在windows下安装GIT 分步阅读 Git是一个免费的.开源的版本控制软件.在Windows上安装git,一般为msysgit,官方下载地址为 http://code.google.com/p ...

  6. js的面向对象的程序设计之理解继承

    来自<javascript高级程序设计 第三版:作者Nicholas C. Zakas>的学习笔记(六) 先来解析下标题——对象和继承~ 一.对象篇 ECMA-262把对象的定义为:&qu ...

  7. Spark 1.60的executor schedule

    第一次看源码还是Spark 1.02.这次看新源码发现调度方式有了一些新的特征,在这里随便写一下. 不变的是,master还是接收Appclient和worker的消息,并且在接收RegisterAp ...

  8. 详细解析: VictorOps 是如何利用和完善 ChatOps?

    ChatOps,即聊天应用,在软件开发中被广泛应用改进开发者之间的沟通.简单地说,ChatOps 是将内容或行动 (或两者) 迁移到聊天客户端.这样做之后,企业内的所有团队都能分享重要信息,行动,及其 ...

  9. 1964-NP

    描述 Problems in Computer Science are often classified as belonging to a certain class of problems (e. ...

  10. TPS和QPS的区别

    一.TPS:Transactions Per Second(每秒传输的事物处理个数),即服务器每秒处理的事务数.TPS包括一条消息入和一条消息出,加上一次用户数据库访问.(业务TPS = CAPS × ...