android listview edittext 事件,Android ListView item中含有Edittext 中一些坑
今天做一個(gè)界面. ?是?一個(gè)列表 .列表中有spinner,button,edittext等控件
首次打開需要展示,用戶可以修改,修改后數(shù)據(jù)保存.
??在保存Edittext控件上的值的時(shí)候,用的etRemark.addTextChangedListener(myTextWatcher)????????
注意?是addTextChangedListener
來監(jiān)聽Edittext的值,如果變化的話 就將變化的值直接存入數(shù)據(jù)集對(duì)象中.
這樣存在了幾個(gè)問題
1,我們改變了一個(gè)editext的值后通過logcat 發(fā)現(xiàn)?onTextChanged會(huì)被多次調(diào)用.
我們知道listview在第一次展示的時(shí)候會(huì)多次調(diào)用getView方法來確定itemView的高度.
多次調(diào)用就會(huì)給同一個(gè)editext控件 add多個(gè)TextChangedListener.
public?void?addTextChangedListener(TextWatcher?watcher)?{
if?(mListeners?==?null)?{
mListeners?=?new?ArrayList();
}
mListeners.add(watcher);
}
也就導(dǎo)致了為什么輸入一次 會(huì)多次調(diào)用TextChangedListener的方法.
2,listview滑動(dòng)后發(fā)現(xiàn)editext的值會(huì)混亂.
如果一屏為3個(gè)item
具體混亂特征為首次加載完listview的時(shí)候.
第一次滑動(dòng),滑倒第二頁的時(shí)候第二屏的第一個(gè)(position=3)會(huì)把第一屏的第一個(gè)item(position=0)給覆蓋掉.如果position=3的這個(gè)item為空的話.再滑到頂部則發(fā)現(xiàn)position的item 也為空了.
這個(gè)時(shí)候在position=0的item中的editext的值改變的時(shí)候,往下滑發(fā)現(xiàn)position=3的也改變了.
我們都知道這是convertView復(fù)用的結(jié)果.
具體原因是,在加載第二屏第一個(gè)的item的時(shí)候調(diào)用的getView()方法,
EditText?et=?ViewHolder.get(convertView,?R.id.item_editText);
et.setText(datas.get(itemPosition).editTextValue);
et.addTextChangedListener(myTextWatcher);
我的代碼里有一個(gè)settext(value)方法,,因?yàn)楹偷谝黄恋膇tem用的是同一個(gè)editext對(duì)象
這個(gè)時(shí)候會(huì)觸發(fā)TextChanged事件,因?yàn)橛玫氖莂ddTextChangedListener方法.所以這個(gè)editext中有多個(gè)listener
插入Textwatcher代碼.
class?MyTextWatcher?implements?TextWatcher{
private?int?position;
public?MyTextWatcher(int?position)?{
super();
this.position?=?position;
}
@Override
public?void?beforeTextChanged(CharSequence?s,?int?start,?int?count,?int?after)?????????????????{
}
@Override
public?void?onTextChanged(CharSequence?s,?int?start,?int?before,?int?count)?{
}
@Override
public?void?afterTextChanged(Editable?s)?{
datas.get(position).editTextValue=?s.toString();
}
}
也會(huì)觸發(fā),所以這個(gè)時(shí)候,就會(huì)調(diào)用afterTextChanged()方法
因?yàn)槲业腡extWatcher對(duì)象中維護(hù)了一個(gè)position的全局變量,其實(shí)這個(gè)TextWatcher的position為0.則把position為3的edittext的值賦給了datas.get(0)editTextValue;所以存在了第一次滑動(dòng)的時(shí)候會(huì)發(fā)現(xiàn)值會(huì)被覆蓋的問題.
等到多次滑動(dòng)后一個(gè)editext控件就會(huì)add多個(gè)TextWatcher對(duì)象,這個(gè)時(shí)候一旦修改一個(gè)editext的值,就會(huì)調(diào)用多個(gè)TextWatcher的textChanged回調(diào),也就是為什么改一個(gè)position為0的editext.怎么也把position為3的editext也改了.
其實(shí)修改的是datas中的值.
怎么解決呢.看了半天廢話終于到點(diǎn)子上了.
1 不復(fù)用converView,并且為listview的item指定高度阻止首次加載多次調(diào)用getView()方法.
但是這樣每次都去inflate布局文件實(shí)在太坑了.
2 不用addTextChangedListener 改用?setOnFocusChangeListener() .靠失去焦點(diǎn)來觸發(fā)保存數(shù)據(jù)
個(gè)人嘗試過后沒問題.但是失去焦點(diǎn).總感覺有點(diǎn)不靠譜.不知道是不是web開發(fā)的后遺癥,怕如果用戶輸入完后直接點(diǎn)擊別的地方的按鈕,會(huì)不會(huì)不會(huì)觸發(fā),(經(jīng)過原生的android測(cè)試,發(fā)現(xiàn)無論是關(guān)閉輸入框,還是點(diǎn)擊別的地方的按鈕,都會(huì)觸發(fā)焦點(diǎn)丟失事件) ?應(yīng)該可以放心使用
3. 還用addTextChangedListener()來觸發(fā)保存,不過在editext賦值之前先remov掉之前的TextWatcher
查看源碼removeTextChangedListener()方法 用的是
public?void?removeTextChangedListener(TextWatcher?watcher)?{
if?(mListeners?!=?null)?{
int?i?=?mListeners.indexOf(watcher);
if?(i?>=?0)?{
mListeners.remove(i);
}
}
}
list的indexOf()方法.
則需要重寫TextWatcher的 equals()方法.
見代碼
MyTextWatcher?myTextWatcher?=?new?MyTextWatcher(itemPosition);
et.removeTextChangedListener(myTextWatcher);
et.setText(datas.get(itemPosition).editTextValue);
et.addTextChangedListener(myTextWatcher);
MyTextWatcher類中重寫
@Override
public?boolean?equals(Object?o)?{
return?true;
}
這樣就可以完美解決了;
總結(jié)
以上是生活随笔為你收集整理的android listview edittext 事件,Android ListView item中含有Edittext 中一些坑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web渗透基础小总结
- 下一篇: Android服务器django,And