Android中Adapter中edittext,checkbox記住狀態解決方案(二)

來源:互聯網
上載者:User

Android中Adapter中edittext,checkbox記住狀態解決方案(二)

Android中Adapter中edittext,checkbox記住狀態解決方案(一)

在上篇文章解決了adapter中checkbox記住狀態和edittext可編輯的問題,下面談談怎麼解決記住edittext中的內容和保證在操作加、減按鈕的時候,操作的edittext對象是沒有錯位的問題。

一、記住edittext中的內容

解決的思路和checkbox差不多,不過還是有些差別,checkbox只有兩種狀態,而edittext的值是不固定的。checkbox我們是用一個enum類型的list來儲存狀態的,所以edittext就不能了,可以用map和實體類,我為了方便就用了hashMap。

 

// 用來儲存editext中資料的listprivate List> mData = new ArrayList>();
在初始化的時候先類比資料

 

 

for (CartBean cartBean : list) {mData.add(new HashMap());}

 

edittext的監聽,並且有個log

            mHolder.num.addTextChangedListener(new TextWatcher() {@Overridepublic void onTextChanged(CharSequence s, int start, int before,int count) {}@Overridepublic void beforeTextChanged(CharSequence s, int start, int count,int after) {}@Overridepublic void afterTextChanged(Editable s) {if (!TextUtils.isEmpty(s.toString())) {                                     if(!TextUtils.isEmpty(s.toString())){mData.get(position).put(etValue,s.toString()); Log.i(afterTextChanged, position+position);}}}});
根據list對應位置的position取出edittext的值

 

 

       String value = mData.get(position).get(etValue);if (!TextUtils.isEmpty(value)) {mHolder.num.setText(value);} else {mHolder.num.setText(1);}
代碼出來了,然後在測試的時候可以發現仍然會出現錯亂的問題,後來當多次來回滑動列表之後,再滑動列表,讓第一個剛好完全出來,下一個剛好進來,這時候第一個item會被剛進來的item重用,執行上面的賦值代碼的時候log應該是這樣

 

 

01-27 15:55:46.612: I/afterTextChanged(4784): position001-27 15:55:46.622: I/afterTextChanged(4784): position101-27 15:55:46.632: I/afterTextChanged(4784): position201-27 15:55:46.642: I/afterTextChanged(4784): position301-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called 01-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called 01-27 15:55:46.662: D/AbsListView(4784): unregisterIRListener() is called 01-27 15:55:46.682: D/AbsListView(4784): unregisterIRListener() is called 01-27 15:55:56.882: I/afterTextChanged(4784): position4
一個操作只觸發一個監聽

 

結果發現是這樣

 

01-27 15:53:43.772: I/afterTextChanged(4784): position001-27 15:53:43.772: I/afterTextChanged(4784): position501-27 15:53:43.772: I/afterTextChanged(4784): position501-27 15:53:43.772: I/afterTextChanged(4784): position901-27 15:53:43.772: I/afterTextChanged(4784): position501-27 15:53:43.772: I/afterTextChanged(4784): position001-27 15:53:43.772: I/afterTextChanged(4784): position601-27 15:53:43.772: I/afterTextChanged(4784): position1501-27 15:53:43.772: I/afterTextChanged(4784): position1501-27 15:53:43.772: I/afterTextChanged(4784): position1101-27 15:53:43.772: I/afterTextChanged(4784): position601-27 15:53:43.772: I/afterTextChanged(4784): position201-27 15:53:43.772: I/afterTextChanged(4784): position801-27 15:53:43.772: I/afterTextChanged(4784): position1201-27 15:53:43.772: I/afterTextChanged(4784): position1801-27 15:53:43.772: I/afterTextChanged(4784): position1301-27 15:53:43.772: I/afterTextChanged(4784): position901-27 15:53:43.772: I/afterTextChanged(4784): position401-27 15:53:43.772: I/afterTextChanged(4784): position4
一個操作觸發了很多個監聽,觸發了多個監聽,就必然會導致多個地方的edittext的值被改變,所以才出現錯亂的問題。後來我想到可能是在adapter反覆執行

 

 

  mHolder.num.addTextChangedListener(new TextWatcher()
的緣故,為了證實自己的想法,我點進去看了下監聽的源碼,發現

 

 

 public void addTextChangedListener(TextWatcher watcher) {        if (mListeners == null) {            mListeners = new ArrayList();        }        mListeners.add(watcher);    }
原來android是用了arraylist把所有加進來的監聽都存起來了,所以才會有一個操作觸發多個監聽的問題。那麼checkbox沒出現這樣的原因應該是每次都重新設定監聽對象了吧

 

 

 public void setOnClickListener(OnClickListener l) {        if (!isClickable()) {            setClickable(true);        }        getListenerInfo().mOnClickListener = l;    }
果然每次都重新設定一個新的。其實根據方法名能夠看出來方法的用途的,一個是add,一個是set。
問題找到那就好辦了,其實adapter中的viewholder對象數目是固定的,在多也只會重用了,所以我們也可以設定和viewholder一樣數量的監聽就行了,可以這樣做

 

 

if (convertView == null) {      ....      class MyTextWatcher implements TextWatcher {public MyTextWatcher() {}       @Overridepublic void onTextChanged(CharSequence s, int start,int before, int count) {}       @Overridepublic void beforeTextChanged(CharSequence s, int start,int count, int after) {}@Overridepublic void afterTextChanged(Editable s) {if (!TextUtils.isEmpty(s.toString())) {mData.get(position).put(etValue, s.toString()); //Log.i(afterTextChanged, position + position);}       }}mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));}
這樣只在convertview為null的時候才添加監聽,這樣保證了一個edittext只會有一個監聽。再試試,發現還是不對,改變過的值都無法儲存。出了問題還是看log

 

 

01-27 16:59:40.512: I/afterTextChanged(12344): position001-27 16:59:40.532: I/afterTextChanged(12344): position101-27 16:59:40.542: I/afterTextChanged(12344): position201-27 16:59:40.552: I/afterTextChanged(12344): position301-27 16:59:42.772: I/afterTextChanged(12344): position401-27 16:59:43.712: I/afterTextChanged(12344): position001-27 16:59:44.502: I/afterTextChanged(12344): position101-27 16:59:45.392: I/afterTextChanged(12344): position201-27 16:59:46.632: I/afterTextChanged(12344): position301-27 16:59:47.492: I/afterTextChanged(12344): position401-27 16:59:47.842: I/afterTextChanged(12344): position001-27 16:59:49.142: I/afterTextChanged(12344): position101-27 16:59:51.662: I/afterTextChanged(12344): position201-27 16:59:52.822: I/afterTextChanged(12344): position301-27 16:59:53.192: I/afterTextChanged(12344): position401-27 17:00:06.662: I/afterTextChanged(12344): position0
看到監聽裡面的position的值是0-4,也就是說無論列表怎麼滑動,position的值都只是convertview為空白的時候初始化好的。這樣當第一項滾出螢幕,底下一項進入螢幕的時候,執行到這段代碼

 

 

//這時代碼position肯定是大於4的,假設是5,但mData中位置為5的地方是空值,這就導致第一項和第6項就都被設為1了String value = mData.get(position).get(etValue);if (!TextUtils.isEmpty(value)) {mHolder.num.setText(value);} else {mHolder.num.setText(1);}
想解決這個問題,就得在監聽回調的方法裡能夠動態擷取到position的值。這裡我們可以這樣做

 

 

        if (convertView == null) {......class MyTextWatcher implements TextWatcher {public MyTextWatcher(ViewHolder holder) {mHolder = holder;}/** * 這裡其實是緩衝了一屏數目的viewholder, 也就是說一屏能顯示10條資料,那麼記憶體中就會有10個viewholder * 在這的作用是通過edittext的tag拿到對應的position,用於儲存edittext的值 */private ViewHolder mHolder;@Overridepublic void onTextChanged(CharSequence s, int start,int before, int count) {}@Overridepublic void beforeTextChanged(CharSequence s, int start,int count, int after) {}@Overridepublic void afterTextChanged(Editable s) {if (!TextUtils.isEmpty(s.toString())) {//通過tag來取position int position = (Integer) mHolder.num.getTag();mData.get(position).put(etValue, s.toString()); //Log.i(afterTextChanged, position + position);}}}mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));convertView.setTag(mHolder);} else {mHolder = (ViewHolder) convertView.getTag();}       //每次用position動態更新edittext的tag       mHolder.num.setTag(position);
雖然viewholder就固定的那幾個,但是我們可以通過edittext的tag從而達到動態更新position值的效果。

 

然後再測試就會發現edittext能夠記住內容了。

二、保證在操作加、減按鈕的時候,操作的edittext對象是沒有錯位的

正常監聽是這樣寫

 

mHolder.add.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {strNum = mData.get(position).get(etValue);int intnum = Integer.parseInt(strNum);intnum++;mHolder.num.setText( + intnum);}});
但這樣寫在adapter中是行不通的, 因為當觸發回調的時候,edittext已經不是add按鈕註冊監聽時候的那個了,而是最後一個載入的item中的edittext。edittext的對象已經變了就是導致操作edittext錯位的根本原因。這個問題的解決方案我在上篇文章裡面已經說過了,就是把edittext存起來。代碼我就不貼了,下面我會貼出demo連結,感興趣的可以下載看看。有什麼好的建議可以留言分享出來,共同學習。

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.