Android 有關在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 讓此方法可進行其他操作,如,把光標切換到下一個輸入框
 } });wujiaox

 

  同時使用了onFocus 事件和 OnKey KEYCODE_ENTER回車事件來獲取輸入框中的值。

  onFocus:()

     ①focus 有兩種一種時獲取焦點一種是失去焦點,我們取失去焦點。所以判斷 !b

    ②由於操作中有新增一行,刪除一行,當刪除光標所在的行也會引發焦點失去的事件,此時postion的條目可能已經移出,所以判斷 data.size()>position

    🌂為了避免一些不必要的賦值操作,所以判斷 當前data 數據集合中的值是否和當前輸入框中的值是否一致,一致就不可以不必再執行賦值操作。所以判斷 !myViewHolder.et.getText().toString().equals(data.get(position).getCheckValue()+"")

    ⭐如果在光標選中行執行刪除方法,adapter刷新之后,holder 的 EditText還是會引發 focus 事件,會將刪除的數據賦值給下個行的數據,難搞哦? 

      處理 : 在 item_layout 中加了一個EditText 在刪除之前將 焦點移動到新建的 EditText 上,這樣數據就會保存,在刪除后就不會再引發 focus 

  onKey KEYCODE_ENTER

    此處判斷同上,用兩個方法結合時為了增加用戶體驗,在最后一行時可以通過回車來保存,在其他行時回車能夠自動定位到下一個輸入框


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM