一、问题原因

我们都知道Android中的adapter的view是用了重用机制的,简单地说就是当屏幕中的item占满屏幕以后,我们滑动listview的时候,第一个item退出屏幕,最后一个item进入屏幕

View getView(final int position, View convertView, ViewGroup parent)
这个时候,getview中convertview就不为空了,它的值就是第一个item的view,我们一般都会通过ViewHolder来缓存item,就不用重复findid了,直接就可以使用缓存的控件了。

这个缓存机制就是导致问题出现的根本原因。可能有人就说了,只要不用convertview来缓存不就能解决问题了么。对于这样的解决方案,我只能说,能使用这种方案的都是用屁股在思考问题!

二、问题解决

1.上面有两个问题,分别是editText和checkBox,我们先从简单的来,checkbox只需要考虑两种状态就行了,所以就先解决checkBox

首先用enum来标记下选中和未选中这两种状态

public enum Type {Checked, UnCheck;}
接着在构造方法里面模拟数据,我这里用typeList来保存checkbox的状态,默认都不选中。
private List list;private List typeList = new ArrayList();public CartAdapter(Context context, List list) {this.list = list;this.context = context;initData();}private void initData() {for (CartBean cartBean : list) {Type type = Type.UnCheck;typeList.add(type);}
接下来,
        mHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {if (isChecked) {typeList.set(position, Type.Checked);} else {typeList.set(position, Type.UnCheck);}}});if (typeList.get(position) == Type.Checked) {mHolder.cb.setChecked(true);} else if (typeList.get(position) == Type.UnCheck) {mHolder.cb.setChecked(false);} else {mHolder.cb.setChecked(false);}
我是先给checkbox注册了监听,当checkbox状态变化的时候,我也相应的改变typeList中对应位置的状态,随后是根据我typeList中存储的状态来设置checkbox是否选中,这样问题就可以解决了。 不过有一点需要强调一下,如果把监听的代码放到设置checkbox状态的代码之后的话,仍然会 出现checkbox状态丢失的问题。这是为什么?文章开头有说过viewholder会缓存item,所以如果监听写在后面的话,当初始化checkBox属性时,由于可能改变其状态,导致调用了onCheckedChange()方法,而这个监听器是在上一次初始化的时候添加的,那么position就是上一次的,不是本次的position,从而导致typeList中的状态错了。

我就举个例子吧,譬如说我选中了第一个item的checkbox,屏幕能显示10个item,当滑动item的时候,第十一个出来,它重用的第一个item的view,checkbox也是第一个的,监听也是第一个的。那么系统在执行这段代码的时候

if (typeList.get(position) == Type.Checked) {mHolder.cb.setChecked(true);} else if (typeList.get(position) == Type.UnCheck) {mHolder.cb.setChecked(false);} else {mHolder.cb.setChecked(false);}

就得把这个checkbox的状态从选中改成未选中的状态,这样就会触发监听事件

public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {if (isChecked) {typeList.set(position, Type.Checked);} else {typeList.set(position, Type.UnCheck);}}
根据这段代码就会把position为0的位置的checkbox的状态设为uncheck。这样一来,当我们滑回去,第一个item重新进入屏幕的时候,我们会发现item的状态丢了,又变成未选中了。

所以为了避免这个问题,每次都必须先注册监听,再根据typelist中存储的状态来设置item是否选中。


checkbox的问题解决了,接下来就是editText的了,这个有点麻烦,大家看我文章开头的图片,我不仅要保存edittext里面的值,还要保证在操作加、减button的时候,操作的edittext对象是正确的,最后还有焦点问题。


2.先说说焦点问题,就是在listview中我们点击editText会发现,软键盘是弹出来了,光标也移到EditText上面了但是,不管输入什么editText里面都不显示!对于这个,我们可以在Activity里面这么配置

android:windowSoftInputMode="adjustPan",这个就是设置输入法的弹出模式,不挤压布局,输入法会覆盖在布局之上,同时editText也会获得焦点。其实之前editText不能输入也是因为没有焦点的缘故,这样就可以解决问题了。也不需要自己动态的获取editText的焦点了。

这个时候edittext能够输入内容了,接下来就是保存内容和button能操作对位的edittext。

我的做法是把edittext这个对象保存在list中,这样的做法不是很好,因为edittext不能序列化存储,我们没法把它持久化存储,这就造成这个对象容易丢。我们都知道系统在横竖屏切换的时候,Activity会重启或者在应用长时间处于后台的时候,系统会把Activity给清掉,等用户回到应用的时候会再重启Activity,如果我们无法存储状态的话,从用户体验上来说就不是很好。或许可以把这个list放在application中静态存储,就和项目中管理所有Activity的list一样。

还没有说完,下篇文章会有demo。


Android中Adapter中edittext,checkbox记住状态解决方案(二)





更多相关文章

  1. Android进入suspend状态(goToSleep)
  2. android状态机statemachine详解
  3. android 游戏开发入门
  4. 【Android】debug 状态下其签名文件 debug.keystore 相关(如何获
  5. 几行代码看程序员的水平——Android文件命名规范
  6. Android应用程序的生命周期
  7. Android之——史上最简单自定义开关按钮的实现
  8. Android(安卓)Power Management
  9. Android根据Button状态(normal,focused,pressed)显示不同背景图

随机推荐

  1. Android(安卓)组建 Content Provider 了
  2. android.mk转换为android.bp
  3. Android(安卓)| 如何给Fragment里的butto
  4. gallery3d源码学习总结(二)
  5. Android应用程序权限机制的源代码分析(2)
  6. GestureDetector简单应用实现长按和双击
  7. Android(安卓)WebView 跳转第三方App
  8. android自定义控件宽高的获取
  9. github优秀的开源库
  10. Android: 微信分享