Android's listview plus checkbox realizes single save checkbox check information

When I was working on a project recently, I wanted to add a function on the Android side, that is, to add an activity with a lot of checkbox information on it, and then you can select multiple checkboxes for people. It seems pretty simple. . But there are a lot of troubles in doing it. .

Although I know a little bit about Android and I have seen some codes before, but I look at other people’s codes. Of course it’s easy to read the codes. Now I have to write them all by myself. This is a bit tricky. At first, I couldn’t get started. I checked it on the Internet and found that there is a good way to write it, which is to import the layout of the adapter with listview, so I started to change it according to his code prototype.


After I changed it for a long time, I finally changed it a little bit, which also spent a lot of energy! ! So write it down while it's hot, so that you don't forget it later. If you forget to write it again, it will be a double job!


The code I added newly has four files, namely Adapter.java, ListViewDemo, java, choice.xml, and problem_item.xml.


Problems encountered and solutions:

1. After the newly created multi-select box is selected, jump to another interface and click on this interface again. The previous multi-select box information cannot be saved, so the selected information cannot be recorded.

Solution: Use preference to save, write the checkbox selection information into the preference, and then read the initialization information to read the previous record information after entering this interface again next time. Thereby, check the record of the check box.


2. Preferences can only be saved as key-value pairs. When this activity has multiple other information boxes called, it will not record all the check box selection information. For example, there are 100 students, you To perform multi-select box operations for each student’s category, such as selecting subjects in class, which activity of the subject is the same, but the data is different, so you need to save the multi-select box data, it’s okay to save one , But you need to use your brain to save everyone’s information.

Solution: Send the ID of each student to the select box activity, and read the key value of the corresponding student ID each time you open it. Because of the multi-select box, there are multiple values. For convenience, I will select all the multi-select boxes. Converted to 01 string, 0 means not selected, 1 means selected. Then parse out whether it is selected.


The following is the corresponding function code, for reference only, not hope to point out:


Inside the red line are small bugs discovered later! !

!!=================================================================================!!

The software always has bugs and needs continuous improvement. I thought that the logic I wrote was clear and there should be no bugs. Later, I encountered a bloody bug during the test, so that Log was added to every line of the key code to check. Run status information, and finally found out that the program was insufficient.

The bug is manifested in that when the length of the multi-select box is modified and the software is reinstalled, clicking the multi-select box interface again will directly exit the program with an error. The reason is that the data of the previous version has not been cleaned up, so that the data is read. I still read the character array of the length of the previous multi-select box, so that the original 6-digit string is assigned to a string greater than 6 digits. Of course, an error will be reported. This bug made me think for a long time. . .


!!=================================================================================!!


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;  
}  

Below is the rendering of the options



Guess you like

Origin blog.csdn.net/u012457196/article/details/38304801