android自定义带多选框的listview并避免出现自动选中另外选项

[align=center][size=x-large][color=red][b]android自定义带多选框的listview[/b][/color][/size][/align]

[align=center][size=medium]先展示下效果图。[/size][/align][align=center][img]http://dl.iteye.com/upload/attachment/0063/7379/607278bb-2d4c-3f73-bd9a-a4d4c830dd6d.jpg[/img][/align]

[size=medium]main.xml[/size]
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ListView
android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>

</LinearLayout>


[size=medium]自定义列表显示样式 list_item.xml[/size]
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher" />

<LinearLayout
android:id="@+id/linearlayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/image"
android:orientation="vertical"
>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="23sp"
android:text="TextView" />

<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
<CheckBox
android:id="@+id/box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
/>

</RelativeLayout>


[size=medium]具体代码如下:[/size]
package org.hwq.list11;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.Toast;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class Main extends Activity {
List<Map<String,String>> data;
ListView lv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
lv = (ListView) findViewById(R.id.listView1);
data = getData();
// SimpleAdapter a = new SimpleAdapter(this,data, R.layout.list_item,from,to);
// lv.setAdapter(a);
MyAdapter adapter = new MyAdapter(this);
lv.setAdapter(adapter);
}
String[] from = new String[]{
"image","name","info"
};
int[] to = new int[]{
R.id.image,R.id.name,R.id.info
};
int[] img = new int[]{
R.drawable.a,R.drawable.b,R.drawable.c
};
String[] name = new String[]{"诸葛","张飞","关羽","刘备","曹操","曹培","曹仁","董卓","吕布","貂蝉","吕蒙","郭嘉","周瑜"};
public List<Map<String,String>> getData(){
List<Map<String,String>> list = new ArrayList<Map<String,String>>();
for(int i=0;i<13;i++){
Map<String,String> map = new HashMap<String, String>();
map.put("image", ""+img[i%3]);
map.put("name", name[i]);
map.put("info", "信息技术");
list.add(map);
}
return list;
}
public class Holder{
public ImageView image;
public TextView name;
public TextView info;
public CheckBox box;
}
public class MyAdapter extends BaseAdapter{
private LayoutInflater inflater;
public MyAdapter(Context context){
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}

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

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

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

Holder holder = null;
if(convertView == null){
holder = new Holder();
convertView = inflater.inflate(R.layout.list_item, null);

holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.name = (TextView) convertView.findViewById(R.id.name);
holder.info = (TextView) convertView.findViewById(R.id.info);
holder.box = (CheckBox) convertView.findViewById(R.id.box);
convertView.setTag(holder);
}else{
holder = (Holder) convertView.getTag();
}

holder.image.setImageResource(Integer.parseInt(data.get(position).get("image")));
holder.name.setText(data.get(position).get("name"));
holder.info.setText(data.get(position).get("info"));
holder.box.setId(position);
holder.box.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
CheckBox box = (CheckBox)buttonView;
Toast.makeText(Main.this, "box 位置"+box.getId()+data.get(box.getId()).get("name"), 0).show();
}
});
return convertView;
}

}
}


[size=medium] 下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。

  系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的list_item.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。[/size]

[b][color=red] [size=medium]上面步骤完成后,你会发现,当你点击一个复选框的时候,竟然能看到,有的复选框莫名也自动给点上了。这个很让人郁闷。这其中的问题,本人也搞不明白,希望高手能解答。下面给出解决方案:[/size][/color][/b]

代码:
package org.hwq.listview3;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


public class Main extends Activity{
//显示数据
private List<Map<String,String>> data =new ArrayList<Map<String,String>>();
private ListView lv;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
lv = (ListView) findViewById(R.id.listview1);
//自定义适配器继承BaseAdapter
MyAdapter adapter = new MyAdapter(this);
lv.setAdapter(adapter);
}
//初始显示数据
private void init() {
for(int i=0;i<20;i++){
Map<String,String> map = new HashMap<String, String>();
map.put("text", "第"+i+"个记录");
data.add(map);
}
}
public class MyAdapter extends BaseAdapter{
LayoutInflater inflater;
//定义CheckBox是否选上的链表,这个很关键
List<Boolean> checked ;
//将要显示的每行View添加到这个map里
Map<Integer,View> map = new HashMap<Integer,View>();
public MyAdapter(Context context) {
inflater = LayoutInflater.from(context);
//初始化checked链表,都置为false,都没选上
checked = new ArrayList<Boolean>();
for(int i=0;i<data.size();i++){
checked.add(false);
}
}
public int getCount() {
//必须返回初始的数据行数,因为ListView要显示多少行,从这里取出
return data.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
//从写getView方法,这个方法是每次ListView要绘制一行记录的时候调用的方法
public View getView(int position, View v1, ViewGroup parent) {
View v;
Holder holder = null;
if(map.get(position) == null){
//如果map中没有这个view记录,依照我们自定义的xml文件生成一个view
v = inflater.inflate(R.layout.list_item, null);
holder = new Holder();
holder.text = (TextView) v.findViewById(R.id.text);
holder.box = (CheckBox) v.findViewById(R.id.box);
map.put(position, v);
final int p = position;
//给CheckBox添加监听器。
holder.box.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
CheckBox b = (CheckBox) v;
//将相应位置的CheckBox的值改变
checked.set(p,b.isChecked());
MyAdapter.this.showData();
}
});
v.setTag(holder);
}else{
v = map.get(position);
holder = (Holder) v.getTag();
}
//说明:CheckBox无法在xml中映射到ListView,所以数据初始化的时候,没有CheckBox
holder.text.setText(data.get(position).get("text"));
holder.box.setChecked(checked.get(position));
return v;
}
protected void showData() {
StringBuffer sb = new StringBuffer();
sb.append("已经选上的记录有:\n");
for(int i=0;i<checked.size();i++){
if(checked.get(i)){
Map<String,String> recode = data.get(i);
sb.append("第").append(i).append("条记录:").append(recode.get("text")).append("\n");
}
}
Toast.makeText(Main.this, sb.toString(), 1).show();
}
}
public final class Holder{
public TextView text;
public CheckBox box;
}
}


[color=darkblue][size=medium]list_item.xml[/size][/color]
[/code]<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

<TextView
android:id="@+id/text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="25sp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
/>
<CheckBox
android:id="@+id/box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
/>

</RelativeLayout>
[size=medium]
[color=blue]main.xml[/color][/size]
[code="java"]<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@+id/listview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值