关于ListView与CheckBox的结合(第一版.杂乱版)

    技术2024-12-04  17

    界面分为两部分:ListView和线性布局的两个按钮 利用ListView显示列表

    这里的布局具有技巧性;ListView的高度=窗口高度-线性布局的高度 那么给ListView设置重要级别layout_weight为1 默认的是0(0是最高的,往后数字越大重要性越低) 这样的话线性布局的重要性就最高了,于是优先布局线性布局,然后将剩余的控件给ListView

    注意ListView里的条目界面只有一个复选框!!! 把数据绑定到每个条目里面。注意item是一个布局,其里面的checkBox是一个控件

    还要给线性布局添加一个背景图片。

    注意

    1  拖动的时候变颜色。ListView有缓存的颜色,所以将其缓存的颜色设置为透明

    2  ListView选择了最前面的两个,但是下一页的前两个也被选中了。适配器对象内部会缓存哪些显示控件(checkBox)被选中了。    当我们再翻到了第二页的时候ListView,要显示控件自然会再次调用适配器对象的getView()方法返回条目的视图对象。所以在翻到第二页    的时候显示的是缓存里面的视图对象。所以次视图对象还是第一页的视图对象,只是对象里面的数字(电话号码)发生了变化    所以也呈现出了被选中的状态。总结:翻到下一页的时候,显示控件是ListView缓存里的,但是数据是从Map里取出来的新数据。      所以:应该根据数据的被选择状态来判断复选框是否被选中,而不是根据显示控件的选择状态来判断复选框被选中

       解决办法:重写simpleAdapter 重写simpleAdapter里面的getView()对象

       复选框的被点击的级别很高,所以在点击的时候实际是点了复选框,而不是条目 所以不能让复选框可以被点击(但是这样的话也就部可以被选中了,然后用代码来使复选框可以

      被选中)

      老师说的按照缓存来解释是不太合理的

    其实没有那么复杂:简单地来说我们的手段就是将数据(电话号码)绑定到一个视图(复选框),数据和视图构成了ListView的每一个条目(即item)。可以这么理解:在ListView注册

    适配器的一瞬间,完成了数据到复选框的绑定。选中了第一页(屏幕)的第一和第二个复选框,但是拉倒第二页的时候,第二页的相同位置依然被选中了。因为:在翻到第二页的时

    候要显示该页的画面,所以要重绘界面即ListView调用了适配器的getView()方法。但是,适配器是按照每页中复选框的ID来记录哪些视图(复选框)被选中,而不是按照所有视图(

    复选框)中复选框的ID来记录,所以重绘的时候,选择的依然是上页的复选框在上页的ID而决定本页显示复选框在本页的ID,所以在相同位置的复选框被现实了。于是我们要重写

    getView()方法。

    所以:应该根据数据(电话号码)的被选择状态来判断复选框是否被选中,而不是根据复选框的选择状态来判断复选框被选中 利用private HashMap<Integer, Boolean> datacheckstate = null;//记录数据(电话号码)的被选状态,key为记录的ID,value为状态。初始时都是为被选中的。

    position指的是map在list中的位置。 checkbox的级别很高,点击条目的时候实际是点击了checkbox!!! 所以让checkbox不可以被点击,不可以被触摸,不可以获得焦点。这样的话checkbox就永远不可以被选中了 于是再采用代码的方式,让checkbox被选中。即在ItemClickListener里面 CheckBox checkBox = (CheckBox)view.findViewById(R.id.checkBox); checkBox.toggle();//对复选框的状态进行切换 datacheckstate.put(rowid, checkBox.isChecked()); 最后一句其实也是利用了复选框的状态决定了数据(电话号码)的被选状态

    在添加和删除黑名单以后要重绘界面

    问题起源: 将电话号码与复选框绑定在一起,利用ListView控件 达到的目的——将复选框被选中的电话号码删除。 但是没有想像的那么简单,会出现的意外状况 1 选中第一页的第2,3个复选框,当翻到第二页的时候其相同位置也被选中   解决思路:绝不能依靠复选框的被选中来删除黑名单号码(原因见上面分析)             所以根据数据的被选择状态决定复选框是否被选中   所以要从条目的点击着手处理!!!!!!!!!条目是数据与视图的结合点。不能简单地从复选框入手。   解决办法:自定义SimpleAdapter类,重写getView()方法。而且借用了外部的全局的balckNumberIsCheckedMap保存了电话号码的状态,初始时均未被选中。 重写SimpleAdapter类的getView()方法主要目的是利用数据的状态来决定CheckBox的状态,初始时CheckBox均未被选中。那么数据的状态是在哪里发生变化的呢?条目被点击的时

    候切换CheckBox的状态,且注意在条目被点击的时候——因为在点击条目的时候可以知道那个数据被点击了即代码: HashMap<String,Object> itemHashMap=(HashMap<String, Object>) lv.getItemAtPosition(position);//得到ListView被点击条目所绑定的HashMap 也就知道了被绑定的电话号码的ID。 利用了一个HashMap<Integer, Boolean> balckNumberIsCheckedMap来保存每个号码的状态,初始时都为false。   2 紧接着带来的问题是,我们在点击条目的时候因为复选框的级别很高,所以实际点击的是复选框   即无法实现条目的点击事件。这样就很糟糕了,因为我们的数据是绑定在ListView的每一个条目   上的,无法处理条目的监听事件,于是就没有什么意义了。   于是在布局文件中使复选框不可以被点击,不可以被触摸,不可以获得焦点!!!   核心思想:利用ListView条目的每次点击来切换CheckBox的状态,然后将CheckBox的状态作为电话号码的  状态!!!!将其号码及其状态存放回到HashMap<Integer, Boolean>  

    balckNumberIsCheckedMap中

      每点击一下就会切换CheckBox的状态!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  

     

     

    关于通过ListView将数据绑定到复选框的问题的总结 问题来源: 1 选中第一页的第2,3个复选框,当翻到第二页的时候其相同位置也被选中   解决思路:绝不能依靠复选框的被选中来删除黑名单号码(原因见上面分析),而依靠哪个数据被选中来删除黑名单.那么怎么知道这个数据是否被选中呢?就是通过             CheckBox的被选状态来提示用户的。所以说CheckBox只是起到一个显示作用!!   解决办法:自定义SimpleAdapter类,重写getView()方法。而且借用了外部的全局的balckNumberIsCheckedMap保存了每个电话号码的状态,初始时均未被选中。             重写getView()方法的目的:             (1)实现数据的绑定checkBox.setText(blacknumber);//这里就是绑定的实质。把这个电话号码绑定到了ListView的这个checkbox上             (2)为CheckBox赋予初始状态(初始状态均为未被选中)             boolean isChecked=balckNumberIsCheckedMap.get(id);             checkBox.setChecked(isChecked); 2 通过实现对于条目点击事件的监听,我们在点击条目的时候可知道是背后的那条数据被点击   即HashMap<String,Object> itemHashMap=(HashMap<String, Object>) lv.getItemAtPosition(position);于是就可以修改此号码在balckNumberIsCheckedMap中的状态   从而用此状态来决定复选框CheckBox的状态,这样的话点击几个条目去实现删除的时候遍历balckNumberIsCheckedMap查看哪些号码被选中,把选中的删除即可。   这样带来了第二个问题:点击条目的时候,其实没有真正地点击到条目,而是点击了复选框CheckBox,因为复选框的优先级很高。    解决办法:在布局文件中使复选框不可以被点击,不可以被触摸,不可以获得焦点!!!于是在点击条目的时候就真的是在点击条目了!!!!!!!!   于是可以这样处理条目点击事件:   (1) 在点击的时候切换复选框状态checkBox.toggle();每点击条目都会切换此状态;然后得到复选框现在的状态即boolean itemIsCheck=checkBox.isChecked();   (2) 得到当前被点击电话号码即HashMap<String,Object> itemHashMap=(HashMap<String, Object>) lv.getItemAtPosition(position);   (3) 得到号码的ID即int blackNumberId=(Integer) itemHashMap.get("id");   (4) 然后修改此号码在balckNumberIsCheckedMap中的状态即balckNumberIsCheckedMap.put(blackNumberId, itemIsCheck);   这样就实现了形式与内容的统一,复选框的状态发生了变化,而且正确体现了实际情况。   核心代码如下:                 checkBox.toggle();                 boolean itemIsCheck=checkBox.isChecked();//得到checkBox目前的状态   HashMap<String,Object> itemHashMap=(HashMap<String, Object>) lv.getItemAtPosition(position);//得到ListView被点击条目所绑定的HashMap     int blackNumberId=(Integer) itemHashMap.get("id");   balckNumberIsCheckedMap.put(blackNumberId, itemIsCheck);

      当我们执行删除的时候:其实就是去HashMap<Integer, Boolean> balckNumberIsCheckedMap看哪些数据被选中了,若被选中就删除它们。

     

     

    最新回复(0)