編輯:關於Android編程
Android中Adapter中edittext,checkbox記住狀態解決方案(一)
在上篇文章解決了adapter中checkbox記住狀態和edittext可編輯的問題,下面談談怎麼解決記住edittext中的內容和保證在操作加、減按鈕的時候,操作的edittext對象是沒有錯位的問題。
一、記住edittext中的內容
解決的思路和checkbox差不多,不過還是有些差別,checkbox只有兩種狀態,而edittext的值是不固定的。checkbox我們是用一個enum類型的list來保存狀態的,所以edittext就不能了,可以用map和實體類,我為了方便就用了hashMap。
// 用來存儲editext中數據的list private List在初始化的時候先模擬數據
for (CartBean cartBean : list) { mData.add(new HashMap()); }
edittext的監聽,並且有個log
mHolder.num.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public 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): position0 01-27 15:55:46.622: I/afterTextChanged(4784): position1 01-27 15:55:46.632: I/afterTextChanged(4784): position2 01-27 15:55:46.642: I/afterTextChanged(4784): position3 01-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): position0 01-27 15:53:43.772: I/afterTextChanged(4784): position5 01-27 15:53:43.772: I/afterTextChanged(4784): position5 01-27 15:53:43.772: I/afterTextChanged(4784): position9 01-27 15:53:43.772: I/afterTextChanged(4784): position5 01-27 15:53:43.772: I/afterTextChanged(4784): position0 01-27 15:53:43.772: I/afterTextChanged(4784): position6 01-27 15:53:43.772: I/afterTextChanged(4784): position15 01-27 15:53:43.772: I/afterTextChanged(4784): position15 01-27 15:53:43.772: I/afterTextChanged(4784): position11 01-27 15:53:43.772: I/afterTextChanged(4784): position6 01-27 15:53:43.772: I/afterTextChanged(4784): position2 01-27 15:53:43.772: I/afterTextChanged(4784): position8 01-27 15:53:43.772: I/afterTextChanged(4784): position12 01-27 15:53:43.772: I/afterTextChanged(4784): position18 01-27 15:53:43.772: I/afterTextChanged(4784): position13 01-27 15:53:43.772: I/afterTextChanged(4784): position9 01-27 15:53:43.772: I/afterTextChanged(4784): position4 01-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原來android是用了arraylist把所有加進來的監聽都存起來了,所以才會有一個操作觸發多個監聽的問題。那麼checkbox沒出現這樣的原因應該是每次都重新設置監聽對象了吧(); } mListeners.add(watcher); }
public void setOnClickListener(OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }果然每次都重新設置一個新的。其實根據方法名能夠看出來方法的用途的,一個是add,一個是set。
if (convertView == null) { .... class MyTextWatcher implements TextWatcher { public MyTextWatcher() {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public 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): position0 01-27 16:59:40.532: I/afterTextChanged(12344): position1 01-27 16:59:40.542: I/afterTextChanged(12344): position2 01-27 16:59:40.552: I/afterTextChanged(12344): position3 01-27 16:59:42.772: I/afterTextChanged(12344): position4 01-27 16:59:43.712: I/afterTextChanged(12344): position0 01-27 16:59:44.502: I/afterTextChanged(12344): position1 01-27 16:59:45.392: I/afterTextChanged(12344): position2 01-27 16:59:46.632: I/afterTextChanged(12344): position3 01-27 16:59:47.492: I/afterTextChanged(12344): position4 01-27 16:59:47.842: I/afterTextChanged(12344): position0 01-27 16:59:49.142: I/afterTextChanged(12344): position1 01-27 16:59:51.662: I/afterTextChanged(12344): position2 01-27 16:59:52.822: I/afterTextChanged(12344): position3 01-27 16:59:53.192: I/afterTextChanged(12344): position4 01-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; @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public 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() { @Override public 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鏈接,感興趣的可以下載看看。有什麼好的建議可以留言分享出來,共同學習。
在Android Support Library19.1版本中,Android工具小組引入了幾個很酷的注解類型,供開發者在工程中使用。Support Libr
1、支持幾乎所有安卓版本,從安卓2.x~7.0安卓4.4、4.4.1和4.4.2是無法支持的,因為當時Google說WebView上傳文件不安全,就去掉了。所以這3個版本
Glide是一款基於Android的圖片加載和圖片緩存組件,它可以最大性能地在Android設備上讀取、解碼、顯示圖片和視頻。Glide可以將遠程的圖片、視頻、動畫圖片等
Intent意圖是android中非常重要的部分,他在Activity,service中有較為廣泛的應用。 1 public void startActiv