這是一篇文字超多的博客,哈哈哈,廢話自行過濾··· 遇到問題 在開發中我們常會在ListView , RecycleView 列表中添加EditText輸入框,或者checkbox覆選框。 覆選框應該是用的比較多的,輸入框淘寶採用的是彈出框的方式,可能在一些特定的情況下,我們希望能夠直接在列表中輸入 ...
這是一篇文字超多的博客,哈哈哈,廢話自行過濾···
-
遇到問題
在開發中我們常會在ListView , RecycleView 列表中添加EditText輸入框,或者checkbox覆選框。
覆選框應該是用的比較多的,輸入框淘寶採用的是彈出框的方式,可能在一些特定的情況下,我們希望能夠直接在列表中輸入,可能會更方便些。
今天說的就是兩個事件
CompoundButton.OnCheckedChangeListener
cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
}
});
TextChangedListener
et.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
}
});
我們可能會在Adapter中使用這兩個方法來監聽選擇Checkbox 和 EditText 的變化。
那麼我們遇到的坑是?
CheckBox
假設我們我有一個全選按鈕,理想效果是:列表全部選中,全選覆選框也選中,如果取消其中一個全選覆選框就不選中,如果選中全選,列表全選,如果取消全選,列表取消選中。如果列表全部選中,取消其中一個,然後就會設置全選為 不選中,那麼就會觸發全選覆選框的checkedchange事件,如果全選從選中變為 未選中,列表全部設置未選中。
說了這麼多,挺複雜的,略過···
然後你以為只是列表中的覆選框和全選覆選框的衝突···你就錯了···實際上不只如此
總之,解決覆選框的問題很簡單,我們不用checkedchange事件,因為這個事件不僅在用戶操作是觸發,其他代碼中的設置也會觸發。直接使用 onclick 點擊事件來控制checkbox 的選中和未選,一定要把選中未選的狀態加到 數據列表中。解決以Myviewholder影響的選中錯亂。
EditText
這個就厲害了,我竟不知道該用什麼事件來代替 TextChangedListener ,由於viewholder減少了view的載入資源耗損,也就是意味著列表中的兩個不是一次載入出來的條目可能使用的是同一個viewholder。
我試過用 焦點離開來做,這個在adapter刷新時還是有一些問題。
為什麼 onclick 事件不會有問題?因為 onclick一定是用戶觸發的,而 TextChanged、onfocus都有可能是adapter刷新獲取其他原因造成你並不想觸發這個這個事件,沒辦法區分開是用戶輸入的還是程式造成的。
其實本來不想寫博客的,checkbox其實入坑不是第一次了,很久沒開發Android,我又入坑了。主要是 EditText 的問題。好吧我看過其他解決方式是將 TextWatcher 事件像 viewholder 一樣儲存起來,但我也並沒有解決問題。
辦法肯定是有的,比如和淘寶一樣彈出輸入框輸入,或者當用戶準備輸入的時候右邊顯示一個小圖標點擊一下用來保存,有點像Web上面的,能想象是什麼樣子嗎,哈哈哈。
-
解決方法
總之我覺得就是找一個能不被其他代碼影響的事件來代替 TextChanged 以及 CheckedChange 事件。 比如 onclick ,其實我覺得 EditText 在 onfocus 事件上稍加處理可能可以,因為onfocus 的影響主要是在 Adapter 刷新的時候會改變,以及用戶操作時會改變。
所以,我的終極解決方案:(忽略這個醜界面)
myViewHolder.et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (!b&&data.size()>position&&!myViewHolder.et.getText().toString().equals(data.get(position).getCheckValue()+"")) {
saveCheckValue(myViewHolder, position);//此方式實現將輸入框數據填充到 data 數據集合中,無其他操作 即 data.get(position).setCheckValue(myViewHolder.et.getText().toString());
}
}
});
myViewHolder.et.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if (data.size()>position&&!myViewHolder.et.getText().toString().equals(data.get(position).getCheckValue()+"")) {
if (i == KeyEvent.KEYCODE_ENTER && keyEvent.getAction() == KeyEvent.ACTION_UP) {
saveCheckValue(myViewHolder, position);
}
}
return false;//返回 false 讓此方法可進行其他操作,如,把游標切換到下一個輸入框
}
});
同時使用了onFocus 事件和 OnKey KEYCODE_ENTER回車事件來獲取輸入框中的值。
onFocus:
①focus 有兩種一種時獲取焦點一種是失去焦點,我們取失去焦點。所以判斷 !b
②由於操作中有新增一行,刪除一行,當刪除游標所在的行也會引發焦點失去的事件,此時postion的條目可能已經移出,所以判斷 data.size()>position