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

Android中Adapter中edittext,checkbox记住状态解决方案(二) Android中Adapter中edittext,checkbox记住状态解决方案(一) 在上篇文章解决了adapter中checkbox记住状态和edittext可编辑的问题,下面谈谈怎么解决记住edittext中的内容和保证在操作加、减按钮的时候,操作的edittext对象是没有错位的问题。 一、记住edittext中的内容 解决的思路和checkbox差不多,不过还是有些差别,ch 阅读详情

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

转载地址:http://blog.youkuaiyun.com/footballclub/article/details/43123105




一、问题原因

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

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

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

二、问题解决

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

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

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

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

[java]  view plain copy
  1. if (typeList.get(position) == Type.Checked) {  
  2.             mHolder.cb.setChecked(true);  
  3.         } else if (typeList.get(position) == Type.UnCheck) {  
  4.             mHolder.cb.setChecked(false);  
  5.         } else {  
  6.             mHolder.cb.setChecked(false);  
  7.         }  

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

[java]  view plain copy
  1. public void onCheckedChanged(CompoundButton buttonView,  
  2.                 boolean isChecked) {  
  3.             if (isChecked) {  
  4.                 typeList.set(position, Type.Checked);  
  5.             } else {  
  6.                 <strong>typeList.set(position, Type.UnCheck);</strong>  
  7.             }  
  8.         }  
根据这段代码就会把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记住状态解决方案(二) 



一、问题原因

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

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

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

二、问题解决

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

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

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

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

[java]  view plain copy
  1. if (typeList.get(position) == Type.Checked) {  
  2.             mHolder.cb.setChecked(true);  
  3.         } else if (typeList.get(position) == Type.UnCheck) {  
  4.             mHolder.cb.setChecked(false);  
  5.         } else {  
  6.             mHolder.cb.setChecked(false);  
  7.         }  

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

[java]  view plain copy
  1. public void onCheckedChanged(CompoundButton buttonView,  
  2.                 boolean isChecked) {  
  3.             if (isChecked) {  
  4.                 typeList.set(position, Type.Checked);  
  5.             } else {  
  6.                 <strong>typeList.set(position, Type.UnCheck);</strong>  
  7.             }  
  8.         }  
根据这段代码就会把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记住状态解决方案(二) 



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


一、问题原因

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

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

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

二、问题解决

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

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

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

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

[java]  view plain copy
  1. if (typeList.get(position) == Type.Checked) {  
  2.             mHolder.cb.setChecked(true);  
  3.         } else if (typeList.get(position) == Type.UnCheck) {  
  4.             mHolder.cb.setChecked(false);  
  5.         } else {  
  6.             mHolder.cb.setChecked(false);  
  7.         }  

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

[java]  view plain copy
  1. public void onCheckedChanged(CompoundButton buttonView,  
  2.                 boolean isChecked) {  
  3.             if (isChecked) {  
  4.                 typeList.set(position, Type.Checked);  
  5.             } else {  
  6.                 <strong>typeList.set(position, Type.UnCheck);</strong>  
  7.             }  
  8.         }  
根据这段代码就会把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记住状态解决方案(二) 



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

在上篇文章解决了adapter中checkbox记住状态和edittext可编辑的问题,下面谈谈怎么解决记住edittext中的内容和保证在操作加、减按钮的时候,操作的edittext对象是没有错位的问题。

一、记住edittext中的内容

解决的思路和checkbox差不多,不过还是有些差别,checkbox只有两种状态,而edittext的值是不固定的。checkbox我们是用一个enum类型的list来保存状态的,所以edittext就不能了,可以用map和实体类,我为了方便就用了hashMap。

[java]  view plain copy
  1. // 用来存储editext中数据的list  
  2. private List<Map<String, String>> mData = new ArrayList<Map<String, String>>();  
在初始化的时候先模拟数据

[java]  view plain copy
  1. for (CartBean cartBean : list) {  
  2.         mData.add(new HashMap<String, String>());  
  3.     }  

edittext的监听,并且有个log

[java]  view plain copy
  1.          mHolder.num.addTextChangedListener(new TextWatcher() {  
  2.   
  3. @Override  
  4. public void onTextChanged(CharSequence s, int start, int before,  
  5.         int count) {  
  6.   
  7. }  
  8.   
  9. @Override  
  10. public void beforeTextChanged(CharSequence s, int start, int count,  
  11.         int after) {  
  12.   
  13. }  
  14.   
  15. @Override  
  16. public void afterTextChanged(Editable s) {  
  17.     if (!TextUtils.isEmpty(s.toString())) {  
  18.                                     
  19.         if(!TextUtils.isEmpty(s.toString())){  
  20.             mData.get(position).put(etValue,  
  21.                     s.toString());  
  22.              <strong>Log.i("afterTextChanged", "position"+position);</strong>  
  23.         }  
  24.     }  
  25. }  
  26. );  
 根据list对应位置的position取出edittext的值

[java]  view plain copy
  1.     String value = mData.get(position).get(etValue);  
  2. f (!TextUtils.isEmpty(value)) {  
  3. mHolder.num.setText(value);  
  4.  else {  
  5. mHolder.num.setText("1");  
代码出来了,然后在测试的时候可以发现仍然会出现错乱的问题,后来当多次来回滑动列表之后,再滑动列表,让第一个刚好完全出来,下一个刚好进来,这时候第一个item会被刚进来的item重用,执行上面的赋值代码的时候log应该是这样

[java]  view plain copy
  1. 01-27 15:55:46.612: I/afterTextChanged(4784): position0  
  2. 01-27 15:55:46.622: I/afterTextChanged(4784): position1  
  3. 01-27 15:55:46.632: I/afterTextChanged(4784): position2  
  4. 01-27 15:55:46.642: I/afterTextChanged(4784): position3  
  5. 01-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called   
  6. 01-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called   
  7. 01-27 15:55:46.662: D/AbsListView(4784): unregisterIRListener() is called   
  8. 01-27 15:55:46.682: D/AbsListView(4784): unregisterIRListener() is called   
  9. <strong>01-27 15:55:56.882: I/afterTextChanged(4784): position4</strong>  
一个操作只触发一个监听

结果发现是这样

[java]  view plain copy
  1. 01-27 15:53:43.772: I/afterTextChanged(4784): position0  
  2. 01-27 15:53:43.772: I/afterTextChanged(4784): position5  
  3. 01-27 15:53:43.772: I/afterTextChanged(4784): position5  
  4. 01-27 15:53:43.772: I/afterTextChanged(4784): position9  
  5. 01-27 15:53:43.772: I/afterTextChanged(4784): position5  
  6. 01-27 15:53:43.772: I/afterTextChanged(4784): position0  
  7. 01-27 15:53:43.772: I/afterTextChanged(4784): position6  
  8. 01-27 15:53:43.772: I/afterTextChanged(4784): position15  
  9. 01-27 15:53:43.772: I/afterTextChanged(4784): position15  
  10. 01-27 15:53:43.772: I/afterTextChanged(4784): position11  
  11. 01-27 15:53:43.772: I/afterTextChanged(4784): position6  
  12. 01-27 15:53:43.772: I/afterTextChanged(4784): position2  
  13. 01-27 15:53:43.772: I/afterTextChanged(4784): position8  
  14. 01-27 15:53:43.772: I/afterTextChanged(4784): position12  
  15. 01-27 15:53:43.772: I/afterTextChanged(4784): position18  
  16. 01-27 15:53:43.772: I/afterTextChanged(4784): position13  
  17. 01-27 15:53:43.772: I/afterTextChanged(4784): position9  
  18. 01-27 15:53:43.772: I/afterTextChanged(4784): position4  
  19. 01-27 15:53:43.772: I/afterTextChanged(4784): position4  
一个操作触发了很多个监听,触发了多个监听,就必然会导致多个地方的edittext的值被改变,所以才出现错乱的问题。后来我想到可能是在adapter反复执行

[java]  view plain copy
  1. mHolder.num.addTextChangedListener(new TextWatcher()  
的缘故,为了证实自己的想法,我点进去看了下监听的源码,发现

[java]  view plain copy
  1. public void addTextChangedListener(TextWatcher watcher) {  
  2.        if (mListeners == null) {  
  3.            <strong>mListeners = new ArrayList<TextWatcher>();</strong>  
  4.        }  
  5.   
  6.        mListeners.add(watcher);  
  7.    }  
原来android是用了arraylist把所有加进来的监听都存起来了,所以才会有一个操作触发多个监听的问题。那么checkbox没出现这样的原因应该是每次都重新设置监听对象了吧

[java]  view plain copy
  1. public void setOnClickListener(OnClickListener l) {  
  2.        if (!isClickable()) {  
  3.            setClickable(true);  
  4.        }  
  5.        <strong>getListenerInfo().mOnClickListener = l;</strong>  
  6.    }  
果然每次都重新设置一个新的。其实根据方法名能够看出来方法的用途的,一个是add,一个是set。
问题找到那就好办了,其实adapter中的viewholder对象数目是固定的,在多也只会重用了,所以我们也可以设置和viewholder一样数量的监听就行了,可以这样做

[html]  view plain copy
  1. if (convertView == null) {  
  2.       ....  
  3.       class MyTextWatcher implements TextWatcher {  
  4.         public MyTextWatcher() {}  
  5.   
  6.   
  7.                @Override  
  8.             public void onTextChanged(CharSequence s, int start,  
  9.                 int before, int count) {  
  10.             }  
  11.   
  12.                @Override  
  13.             public void beforeTextChanged(CharSequence s, int start,  
  14.                 int count, int after) {  
  15.             }  
  16.   
  17.             @Override  
  18.             public void afterTextChanged(Editable s) {  
  19.                 if (!TextUtils.isEmpty(s.toString())) {  
  20.                     mData.get(position).put(etValue, s.toString()); //  
  21.                     Log.i("afterTextChanged", "position" + position);  
  22.                 }  
  23.                }  
  24.     }  
  25.   
  26.             mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));  
  27. }  
这样只在convertview为null的时候才添加监听,这样保证了一个edittext只会有一个监听。再试试,发现还是不对,改变过的值都无法保存。出了问题还是看log

[java]  view plain copy
  1. 01-27 16:59:40.512: I/afterTextChanged(12344): position0  
  2. 01-27 16:59:40.532: I/afterTextChanged(12344): position1  
  3. 01-27 16:59:40.542: I/afterTextChanged(12344): position2  
  4. 01-27 16:59:40.552: I/afterTextChanged(12344): position3  
  5. 01-27 16:59:42.772: I/afterTextChanged(12344): position4  
  6. 01-27 16:59:43.712: I/afterTextChanged(12344): position0  
  7. 01-27 16:59:44.502: I/afterTextChanged(12344): position1  
  8. 01-27 16:59:45.392: I/afterTextChanged(12344): position2  
  9. 01-27 16:59:46.632: I/afterTextChanged(12344): position3  
  10. 01-27 16:59:47.492: I/afterTextChanged(12344): position4  
  11. 01-27 16:59:47.842: I/afterTextChanged(12344): position0  
  12. 01-27 16:59:49.142: I/afterTextChanged(12344): position1  
  13. 01-27 16:59:51.662: I/afterTextChanged(12344): position2  
  14. 01-27 16:59:52.822: I/afterTextChanged(12344): position3  
  15. 01-27 16:59:53.192: I/afterTextChanged(12344): position4  
  16. 01-27 17:00:06.662: I/afterTextChanged(12344): position0  
看到监听里面的position的值是0-4,也就是说无论列表怎么滑动,position的值都只是convertview为空的时候初始化好的。这样当第一项滚出屏幕,底下一项进入屏幕的时候,执行到这段代码

[java]  view plain copy
  1. //这时代码position肯定是大于4的,假设是5,但mData中位置为5的地方是空值,这就导致第一项和第6项就都被设为1了  
  2. String value = mData.get(position).get(etValue);  
  3.         if (!TextUtils.isEmpty(value)) {  
  4.             mHolder.num.setText(value);  
  5.         } else {  
  6.             mHolder.num.setText("1");  
  7.         }  
想解决这个问题,就得在监听回调的方法里能够动态获取到position的值。这里我们可以这样做

[html]  view plain copy
  1.      if (convertView == null) {  
  2. ......  
  3.   
  4. class MyTextWatcher implements TextWatcher {  
  5.     public MyTextWatcher(ViewHolder holder) {  
  6.         mHolder = holder;  
  7.     }  
  8.   
  9.     /**  
  10.      * 这里其实是缓存了一屏数目的viewholder, 也就是说一屏能显示10条数据,那么内存中就会有10个viewholder  
  11.      * 在这的作用是通过edittext的tag拿到对应的position,用于储存edittext的值  
  12.      */  
  13.     private ViewHolder mHolder;  
  14.   
  15.     @Override  
  16.     public void onTextChanged(CharSequence s, int start,  
  17.             int before, int count) {  
  18.     }  
  19.   
  20.     @Override  
  21.     public void beforeTextChanged(CharSequence s, int start,  
  22.             int count, int after) {  
  23.     }  
  24.   
  25.     @Override  
  26.     public void afterTextChanged(Editable s) {  
  27.         if (!TextUtils.isEmpty(s.toString())) {  
  28.             //通过tag来取position<strong>  
  29.          int position = (Integer) mHolder.num.getTag();</strong>  
  30.             mData.get(position).put(etValue, s.toString()); //  
  31.             Log.i("afterTextChanged", "position" + position);  
  32.         }  
  33.     }  
  34. }  
  35.   
  36. mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));  
  37.   
  38. convertView.setTag(mHolder);  
  39.  else {  
  40. mHolder = (ViewHolder) convertView.getTag();  
  41.   
  42.     //每次用position动态更新edittext的tag  
  43.    <strong> mHolder.num.setTag(position);</strong>  
虽然viewholder就固定的那几个,但是我们可以通过edittext的tag从而达到动态更新position值的效果。

然后再测试就会发现edittext能够记住内容了。

二、保证在操作加、减按钮的时候,操作的edittext对象是没有错位的

正常监听是这样写

[java]  view plain copy
  1. mHolder.add.setOnClickListener(new OnClickListener() {  
  2.   
  3.             @Override  
  4.             public void onClick(View v) {  
  5.                 strNum = mData.get(position).get(etValue);  
  6.                 int intnum = Integer.parseInt(strNum);  
  7.                 intnum++;  
  8.                 mHolder.num.setText("" + intnum);  
  9.             }  
  10.         });  
但这样写在adapter中是行不通的, 因为当触发回调的时候,edittext已经不是add按钮注册监听时候的那个了,而是最后一个加载的item中的edittext。edittext的对象已经变了就是导致操作edittext错位的根本原因。 这个问题的解决方法我在上篇文章里面已经说过了,就是把edittext存起来。代码我就不贴了,下面我会贴出demo链接,感兴趣的可以下载看看。有什么好的建议可以留言分享出来,共同学习。

点击前去下载Demo



一、问题原因

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

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

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

二、问题解决

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

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

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

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

[java]  view plain copy
  1. if (typeList.get(position) == Type.Checked) {  
  2.             mHolder.cb.setChecked(true);  
  3.         } else if (typeList.get(position) == Type.UnCheck) {  
  4.             mHolder.cb.setChecked(false);  
  5.         } else {  
  6.             mHolder.cb.setChecked(false);  
  7.         }  

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

[java]  view plain copy
  1. public void onCheckedChanged(CompoundButton buttonView,  
  2.                 boolean isChecked) {  
  3.             if (isChecked) {  
  4.                 typeList.set(position, Type.Checked);  
  5.             } else {  
  6.                 <strong>typeList.set(position, Type.UnCheck);</strong>  
  7.             }  
  8.         }  
根据这段代码就会把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记住状态解决方案(二) 


解决 Adapter 多个 Item 存在 EditText 监听输入问题 DevUtils Github 解决 Adapter 多个 Item 存在 EditText 监听输入问题 -> EditTextWatcherAssist.java 方法 注释 bindListener 绑定事件 package dev.assist; import android.text.Editable; import android.text.TextUt... 阅读详情

相关推荐

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

一、问题原因 我们都知道Android中的adapter的view是用了重用机制的,简单地说就是当屏幕中的item占满屏幕以后,我们滑动listview的时候,第一个item退出屏幕,最后一个item进入屏幕 View getView(final int position, View convertView, ViewGroup parent)这个时候,getview中convertview就

Huxq的博客 5108

android 解决ListView Adapter嵌入EditText 数据重复刷新问题

背景 最近在开发答题类App,其中涉及到有多个填空题的这种可能。对于这种需求我就采用传统的ListVIew+Adapter的这种新式。(Ps:答题里面混合了单选、多选、填空、判断常见题型,其实就是为了方便)。主要是讲Adapter嵌入EditText所遇到的坑,给大家上一张效果图。 这是多个填空题出现的界面,其中遇到的问题就是多个输入框输入内容的时候,经过调试可知,键盘关闭的时候会再一次执...

qq_34993234的博客 1252

Android ListView高级应用:集成CheckBox、Button、EditText

在Android开发中,Adapter是连接数据源和ListView界面的桥梁。为了在ListView中使用CheckBox,我们需要创建一个自定义的Adapter类,这个类将继承自BaseAdapter或者其子类。在这个自定义的Adapter中,我们将添加逻辑来实例化包含CheckBox的视图。@Override@Override@Override@Override} else {// 设置默认选中状态// 检查特定位置的CheckBox是否应该被选中。

weixin_35899324的博客 772

Android 之 ListView 的 checkbox 错位问题解决

作为ListView经典问题之一,如果你尝试过自定义ListView的item,在上面带有一个checkbox的话,那么 当你的item数超过了一页的话,就会出现这个问题,下面我们来分析下出现这种问题的原因,以及如何来 解决这个问题!的东东,平时我们ListView上可见的Item处于内存中,而且他的Item则放在 这个Recycler中,第一次加载item时,当前页面中的convertView都为NULL,当滚出屏幕,这是时候。我们可以写个简单的例子,跟下log,下面是运行后的一些Log图!

leyang0910的博客 379

使用OpenTK展示3D点云图像(C#)

图中存在一个空的点,可通过阈值分割过滤掉,然后如何保证某个点必然存在后面两个和它构成三角形的点,用一个2x2的结构元腐蚀阈值分割出的区域,得到剩下所有的点必然每个点可以构成三角形,这种得到三角形的算法效率会非常高。然后还有光照,无光照和有光照效果差异很大,处理光照核心在于得到每个点的法向量,用上面的三角形的两条边构成的向量叉乘,及得到这个点的法向量,输入给着色器处理得到光照的渲染效果,如下面两张图对比。我们需要把点连成面,有很多算法可以实现,但我拿到的图为一张tif格式16位的深度图,如下图。

海盗Isaac 2283

西红柿成熟度检测数据集总结

成熟度类别标注数量semiripe(半成熟)10275rotten(腐烂)13470fullyripe(完全成熟)35031unripe(未成熟)26212。

crz1336768325的博客 2125

android adapter edittext 聚焦,Android中Adapter中edittext,checkbox记住状态解决方案(1)...

Android中Adapter中edittext,checkbox记住状态解决方案(一)一、问题原因我们都知道Android中的adapter的view是用了重用机制的,简单地说就是当屏幕中的item占满屏幕以后,我们滑动listview的时候,第一个item退出屏幕,最后一个item进入屏幕View getView(final int position, View convertView, Vi...

weixin_29663861的博客 575

虎符+红明谷+ctfshow渔人杯赛后复现

目录标题虎符CTFWeb-签到MISC-你会日志分析吗红明谷CTFWeb-write_shellMISC-我的心是冰冰的ctfshow渔人杯签到抽奖感受下气氛神仙姐姐阿拉丁迷飘啊飘简单二维码我跟你拼了 虎符CTF Web-签到 参考详细分析PHP源代码后门事件及其供应链安全启示 根据文章提示,添加恶意请求头 User-Agentt: zerodiumphpinfo(); 可以看到phpinfo内容 继续构造,查看根目录下的文件 User-Agentt: zerodiumsystem('ls /');

Atkx's Blog 1983

Android ListView Item含有RadioButton、CheckBox、RatingBar、EditText

ListView在项目里面会经常遇到,但是有时候在使用的过程中会遇到一些让我们意想不到的问题,ListView的复用问题在前面的博客中已经介绍过了点击浏览ListView的复用问题。这边博客主要是关于什么的呢?先来看看效果图 这一篇可以说是关于ListView的复用的经常用到的事例。单选,多选,星星的滑动和修改保存EditText的内容 单选的不单单是复用的问题,之所以可以实现单选就是我们大

刘永祥的专栏 2415

生成对抗网络——CGAN(代码+理解)

CGAN(Conditional Generative Adversarial Network)模型是一种 深度学习模型,属于生成对抗网络(GAN)的一种 变体。它的 基本思想是通过 训练生成器和判别器两个网络,使生成器能够生成与给定条件 相匹配的 合成数据,而判别器则 负责区分真实数据和 生成数据。相比于GAN它引入了条件信息(y),使得生成器可以生成与给定条件相匹配的合成数据,从而提高了生成数据的可控性和针对性。

CXDNW的博客 1万+

实战封神!YOLOv7 轻量化部署全攻略:ONNX格式转换+TensorRT极致加速(速度直接提升3-5倍,精度无损)

部署核心链路,这是YOLO系列部署的最优解,速度提升3~5倍,精度无损;ONNX是桥梁:解决模型兼容性问题,简化后能去掉冗余节点,是TensorRT加速的前提;TensorRT是核心:NVIDIA显卡的极致加速引擎,FP16量化是速度与精度的最优平衡,无需手动配置,一键开启;轻量化终极组合YOLOv7-tiny + 416尺寸 + TensorRT FP16,速度提升5~8倍,满足所有实时检测场景;避坑核心:转换参数必加,推理尺寸必须一致,engine文件显卡专属。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 308

ListView中CheckBox和EditText重用问题解决方法

本人刚开始写博客,欢迎提issure; 面试时遇到直接上机实现用ListView实现同时包含EditText和CheckBox要求不允许有任何的混乱,而且得优化。面试一时没有实现,遂回来写成博客,让大家以后不要再踩此坑。ListVeiw的Item<EditText android:id="@+id/et_text" android:layout_width="0dp" an

HockGod的博客 963

DeepSeek+Cline:开启自动化编程新纪元

随着 AI 技术不断进步,编程领域迎来效率变革。DeepSeek 与 Cline 的结合,成为自动化编程的强大工具。DeepSeek 凭借先进的自然语言处理能力,能精准理解编程需求;Cline 作为 VSCode 插件,可实现代码生成、调试、注释等功能的无缝衔接。本文详细阐述二者安装配置、实战操作流程,涵盖从基础代码生成到复杂项目开发的应用技巧,同时解答常见问题,帮助开发者快速掌握这对 “智能搭档”,提升编程效率,解锁自动化编程的无限可能。

邓邓子的博客 6254

当ListView的item为CheckBox,EditText,Spinner的时候处理滑动数据错乱

还记得自己第一次解决listView嵌套数据错乱问题,所以写个笔记记录一下,希望对看到的各位有所帮助。

fire_nirvana的博客 1643

【C语言】一文搞懂C语言文件操作

读写文件、文件相关库函数详解、文件缓冲区介绍

StackFrame 5657

YOLOv11涨点改进 | 全网独家创新,损失函数改进篇 | TGRS 2025 | 引入AdaFocalLoss损失函数,改进小目标检测,自适应聚焦小目标与样本分布不平衡,提升检测精度与训练稳定性

本文提出了一种改进YOLOv11模型的AdaFocalLoss损失函数,通过动态调节机制有效提升小目标检测性能。AdaFocalLoss融合了目标尺寸感知和IoU引导的自适应调节,解决了传统损失函数在小目标检测中的样本不平衡问题。该方法自动调整训练权重,无需手动调参,显著提升了模型在多尺度目标、复杂背景下的检测精度和训练稳定性。实验表明,AdaFocalLoss能更好地平衡不同尺度目标的梯度分布,改善边界完整性,减少误检漏检。文章详细介绍了算法原理、实现代码和在YOLOv11中的集成方法,为提升目标检测性能

Ai缝合怪、助力小伙伴高效发论文 335

关于ListView+checkbox+edittext错乱问题的总结

这里其他的代码就不贴了,主要就是adapter中的代码。 大概的思路就是把对应的值放到对应控件的tag中去,当需要显示的时候拿出来用,类似于listview解决imageView错乱的问题。方法都差不多,在这里记录下。 关于checkbox错乱: viewHolder.checkBox.setChecked(bean.isChecked()); viewHolder.check...

九龙冰哥 563

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Android开发ListView中含有checkBox或者Button时会遇到的难题

android开发经常会遇到ListView中含有checkBox和Button的情况,这里主要会有三个问题,下面分别论述:        1.         ListView中含有checkBox或者Button时,listView的item无法响应点击事件,这主要是因为checkBox和Button等获取焦点的能力高于listView,此时应该让其子控件不能获取焦点,即在布局文件中设置子控

beibeixiao的专栏 1420

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

android listView EditText获取焦点

今天做项目,有一个需要listView界面,需要添加一个EditText输入。开始的思路为屏蔽所有子控件,由setOnItemClickListener总控制界面焦点 listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override p

风晴 1315

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

SharedPreferences 自动登陆 记住密码

public class MainActivity extends Activity implements OnClickListener { private EditText edit_name; private EditText edit_pwd; private CheckBox check_mima; private CheckBox check_login; private...

W2597645565的博客 247

关于ListView中加入并选取checkbox错位的问题

Android ListView CheckBox状态错乱 http://www.cnblogs.com/wujd/archive/2012/08/17/2635309.html 在ListView中的列表项中定义checkbox是一个常见手法,不过如果在listview使用了ViewHolder缓存的话就会遇到一个很恶心的问题,就是列表项错位的问题,为此我想到了一个自认为还算简单的解决方法,就

gundumw100的专栏 387

ListView和CheckBox的混乱问题

[置顶] ListView和CheckBox的混乱问题 标签: androidlistviewcheckbox 2015-12-22 13:36 198人阅读 评论(1) 收藏 举报  分类: 小工具(3)  版权声明:本文为博主原创文章,未经博主允许不得转载。 主要是解决我以前的一篇博客仿微信添加群聊界面——addView里list

u012845099的博客 540

Android开发详解:第4章《UI 控件》

在表4.1中,只给出了TextView控件常用的部分属性,关于该控件的其他属性,可以参阅Android官方提供的API文档。在下载SDK时,如果已经下载Android API文档,那么可以在已经下载好的SDK文件夹下找到(docs文件夹中的内容即为API文档),否则需要自行下载。例如,在屏幕中添加一个文本框,显示文字为“奋斗就是每一天都很难,可一年比一年容易。行,当文本框中的文本超过一行时,其超出的部分将被省略,同时在结尾处添加“…用于指定该文本框中显示的文本内容,可以直接在该属性值中指定,也可以通过在。

m0_67060810的博客 1076

Android常用控件(更新中)

最近在学Android,前后算起来都半个月了,可还是没什么进步,都是些控件。发现控件虽不难,但是很多,脑子一团凌乱,因此整理了一下,以便使用。

WriteOnRead 1433
上一篇: Android开发总结
下一篇: Android Manifest.xml 结构详解
fancylovejava
博客等级 码龄16年 1052粉丝 184原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值