最近做一个项目时想要增加安卓端的一个功能,就是增加一个activity上面有很多checkbox的勾选信息,然后可以给人选择多选框,看起来还算很简单。。但是真正做起来就有很多麻烦了。。
虽然我对安卓有点了解,以前也看过一些代码,但都是看别人的代码,看代码当然简单啦,这下要全部自己写,这下有点棘手了,一开始真是无从下手啊,后来去网上查了一下,觉得有个人的写法不错,就是用listview导入adapter的布局这样子,于是我就照着他的代码的原型开始改了起来。
改了N久,终于改的有点样子了,其中也花了很多精力呢!!所以趁热先记录下来,免得以后忘了,忘了再写的话那可是事倍工半呢!
我新添加的代码有四个文件,分别是Adapter.java,ListViewDemo,java,choice.xml,problem_item.xml这四个文件。
遇到的问题及解决方案:
1.新建的多选框选定以后跳转到别的界面后再次点入这个界面后以前的多选框信息不能保存,这样选择的信息就不能记录下来了。
解决方案:应用preference进行保存,将多选框选择信息写进了preference后下一次再次进入这个界面后就读取初始化信息来进行读取以前的记录信息。从而将多选框的记录勾上。
2.preference只能以键值对来保存,当这个activity有多个其他的信息框调用时,就会产生不能记录所有的多选框选择信息,举个例子,就好像有100个学生,你要为每个学生的类别进行多选框操作,比如说选择上课科目之类的,科目的哪个activity是一样的,但是数据不一样,这样你就需要保存多选框数据了,保存一个还好,但要保存每一个人的信息的话就需要动一番脑筋了。
解决方案:将每一个学生的ID发送到选择框activity,每次打开时读取对应学生ID对于的键值,因为多选框,所以有多个值,为了方便我就将全部的多选框转换为01字符串,0代表没有选中,1代表选中。然后再解析出是否被选中就可以了。
下面是相应功能代码,只供借鉴,不足望指出:
Adapter.java
public class Adapter extends BaseAdapter{ private ArrayList<String> list;//填充数据的list private static HashMap<Integer,Boolean> isSelected;//用来控制checkBox的选中情况 private Context context;//上下文 private LayoutInflater inflater=null;//用来导入布局 public Adapter(ArrayList<String> list,Context context)//构造器 { this.context = context; this.list = list; inflater = LayoutInflater.from(context); isSelected = new HashMap<Integer, Boolean>(); initDate();//初始化数据 } //初始化选择判断为false private void initDate() { for(int i=0;i<list.size();i++) { isSelected.put(i, false); } } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int position) { // TODO Auto-generated method stub return list.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 ViewHolder holder = null; if(convertView==null) { holder = new ViewHolder(); convertView=inflater.inflate(R.layout.problem_item,null);//导入布局并且赋给convertview holder.tv =(TextView)convertView.findViewById(R.id.item_tv);//故障信息 holder.cb =(CheckBox)convertView.findViewById(R.id.item_cb);//勾选框 convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 设置list中TextView的显示 holder.tv.setText(list.get(position)); // 根据isSelected来设置checkbox的选中状况 holder.cb.setChecked(getIsSelected().get(position)); return convertView; } public static HashMap<Integer,Boolean> getIsSelected() { return isSelected; } public static void setIsSelected(HashMap<Integer,Boolean> isSelected) { Adapter.isSelected = isSelected; }
ListViewDemo.java
public class ListViewDemo extends Activity { private ListView lv; private Adapter mAdapter; private ArrayList<String> list; private Button bt_selectall; private Button bt_cancel; private Button bt_deselectall; private Button bt_yes; private int checkNum; // 记录选中的条目数量 private TextView tv_show;// 用于显示选中的条目数量 private int id;//消息编号,用来存储故障标号,从上一个界面传来 private String defaul="";//默认的全部不勾选 private String selectall="";//全部勾选 /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.choice); Intent i=getIntent(); Bundle b=i.getBundleExtra("ID"); id=b.getInt("id"); /* 实例化各个控件 */ lv = (ListView)findViewById(R.id.list); bt_selectall = (Button) findViewById(R.id.bt_selectall); bt_cancel = (Button) findViewById(R.id.bt_cancelselectall); bt_deselectall = (Button) findViewById(R.id.bt_deselectall); bt_yes=(Button) findViewById(R.id.ok); tv_show = (TextView) findViewById(R.id.tv); list = new ArrayList<String>(); initDate(); //初始化勾选框信息,默认都是以未勾选为单位 for(int n=0;n<list.size();n++) { defaul =defaul +"0"; selectall= selectall +"1"; } // 为Adapter准备数据 // 实例化自定义的MyAdapter mAdapter = new Adapter(list, this); // 绑定Adapter lv.setAdapter(mAdapter); getCheck();//获取信息,也可说是初始化信息 // // 全选按钮的回调接口 bt_selectall.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 遍历list的长度,将MyAdapter中的map值全部设为true for (int i = 0; i < list.size(); i++) { Adapter.getIsSelected().put(i, true); } // 数量设为list的长度 checkNum = list.size(); // 刷新listview和TextView的显示 dataChanged(); } }); // 取消按钮的回调接口 bt_cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 遍历list的长度,将已选的按钮设为未选 for (int i = 0; i < list.size(); i++) { if (Adapter.getIsSelected().get(i)) { Adapter.getIsSelected().put(i, false); checkNum--;// 数量减1 } } // 刷新listview和TextView的显示 //dataChanged(); } }); // 反选按钮的回调接口 bt_deselectall.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 遍历list的长度,将已选的设为未选,未选的设为已选 for (int i = 0; i < list.size(); i++) { if (Adapter.getIsSelected().get(i)) { Adapter.getIsSelected().put(i, false); checkNum--; } else { Adapter.getIsSelected().put(i, true); checkNum++; } } // 刷新listview和TextView的显示 //dataChanged(); } }); //确定返回的按钮 bt_yes.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String str="";//确定后直接将信息写入preference保存以备下一次读取使用 for(int i=0;i<list.size();i++) { if(Adapter.getIsSelected().get(i)) { str= str+'1'; } else { str = str+'0'; } } saveCheck(String.valueOf(id),str);//将数据已字符串形式保存起来,下次读取再用 finish(); } }); //绑定listView的监听器 lv.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { // 取得ViewHolder对象,这样就省去了通过层层的findViewById去实例化我们需要的cb实例的步骤 ViewHolder holder = (ViewHolder) arg1.getTag(); // 改变CheckBox的状态 holder.cb.toggle(); // 将CheckBox的选中状况记录下来 Adapter.getIsSelected().put(arg2, holder.cb.isChecked()); // // 调整选定条目 if (holder.cb.isChecked() == true) { checkNum++; } else { checkNum--; } // 用TextView显示 //tv_show.setText("已选中"+checkNum+"项"); } }); } //得到保存在这个activity中的数据 public void getCheck() { SharedPreferences mPerferences=PreferenceManager.getDefaultSharedPreferences(this);//获取默认的preference //获取activity私有的preference SharedPreferences m_private=this.getPreferences(MODE_PRIVATE); String counter=mPerferences.getString(String.valueOf(id), defaul);//如果没有获取到的话默认是0 for(int i=0;i<list.size();i++) { if(counter.charAt(i)=='1') { Adapter.getIsSelected().put(i, true); } } } //保存需要保存的数据 public void saveCheck(String ID,String data) { //保存shuju SharedPreferences mPerferences=PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences m_private=this.getPreferences(MODE_PRIVATE); SharedPreferences.Editor mEditor=mPerferences.edit(); mEditor.putString(ID, data); mEditor.commit(); } // 初始化数据 private void initDate() { for (int i = 0; i < 15; i++) { list.add("data" + " " + i); } } // 刷新listview和TextView的显示 private void dataChanged() { // 通知listView刷新 mAdapter.notifyDataSetChanged(); // TextView显示最新的选中数目 //tv_show.setText("已选中" + checkNum + "项"); //这个功能还不完善,保存后再打开没把这个保存进去,会算错。 }
choic.xml
<RelativeLayout 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/list" android:layout_width="fill_parent" android:layout_height="400dp" /> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/bt_selectall" android:gravity="center" /> <Button android:id="@+id/bt_selectall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/list" android:layout_gravity="bottom" android:text="全选" /> <Button android:id="@+id/bt_cancelselectall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/bt_selectall" android:layout_below="@+id/list" android:text="取消选择" /> <Button android:id="@+id/bt_deselectall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/list" android:layout_toRightOf="@+id/bt_cancelselectall" android:text="反选" /> <Button android:id="@+id/ok" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/list" android:layout_toRightOf="@+id/bt_deselectall" android:text="确定" /> </RelativeLayout>
problem_item.xml
<?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="horizontal" > <TextView android:id="@+id/item_tv" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center_vertical" /> <CheckBox android:id="@+id/item_cb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" android:focusableInTouchMode="false" android:gravity="center_vertical" /> </LinearLayout>
ViewHolder.java
public class ViewHolder { public TextView tv = null; public CheckBox cb = null; }
下面是选项的效果图