一 引言
之前這里發(fā)布過一個RecyclerView中解決EditText各類異常的方案,存在BUG,為了方便后來人誤入這里,我把最新修復(fù)過的版本,搬到這里來了
二 效果圖(2.34 MB)

三 解決方案
- 解析整個問題點之前,先把項目的完整demo放送給大家,地址如下:
https://github.com/kaxi4it/EditTextInRecyclerViewDemo
注:閱讀以下文章時,建議對照demo代碼對比觀看
??因為有EditText的存在,所以demo里加入了InputMethodManager來管理軟鍵盤的隱藏顯示;
??EditText的輸入內(nèi)容,通過一個SparseArray來做管理,因為SparseArray比HashMap更省內(nèi)存,在某些條件下性能更好,主要是因為它避免了對key的自動裝箱(int轉(zhuǎn)為Integer類型),它內(nèi)部則是通過兩個數(shù)組來進(jìn)行數(shù)據(jù)存儲的,一個存儲key,另外一個存儲value,為了優(yōu)化性能,它內(nèi)部對數(shù)據(jù)還采取了壓縮的方式來表示稀疏數(shù)組的數(shù)據(jù),從而節(jié)約內(nèi)存空間;
??EditText的焦點,我們可以通過一個int變量記錄他在adapter中的位置
//輸入法
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//edittext里的文字內(nèi)容集合
SparseArray<String> etTextAry = new SparseArray();
//edittext的焦點位置
int etFocusPos = -1;
TextWatcher textWatcher = new TextWatcher() {
@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) {
//每次修改文字后,保存在數(shù)據(jù)集合中
etTextAry.put(etFocusPos, s.toString());
}
};
??然后分別在onViewAttachedToWindow(item在頁面中顯示)與onViewDetachedFromWindow(item在頁面中隱藏)方法中,做獲取/取消焦點,添加/刪除EditText的文本變化的監(jiān)聽,為何要通過這2個方法來操作,因為RecyclerView的列表緩存機(jī)制,會導(dǎo)致并不是每次item的顯示都會運(yùn)行onBindViewHolder方法,所以容易引起一些頁面的異常情況。
@Override
public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
ItemHolder viewHolder = (ItemHolder) holder;
//刪除文字變化監(jiān)聽器
viewHolder.et.removeTextChangedListener(textWatcher);
//清除焦點
viewHolder.et.clearFocus();
//如果當(dāng)前隱藏的item是焦點所在的位置,那么隱藏輸入法,否則輸入法不會自動關(guān)閉
if (etFocusPos == holder.getAdapterPosition()) {
inputMethodManager.hideSoftInputFromWindow(((ItemHolder) holder).et.getWindowToken(), 0);
}
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
super.onViewAttachedToWindow(holder);
ItemHolder viewHolder = (ItemHolder) holder;
//添加文字變化監(jiān)聽器
viewHolder.et.addTextChangedListener(textWatcher);
//如果當(dāng)前顯示的item是焦點記錄位置,那么獲取焦點,并把光標(biāo)位置置于文字最后,需要顯示輸入法的話可自行添加操作
if (etFocusPos == holder.getAdapterPosition()) {
viewHolder.et.requestFocus();
viewHolder.et.setSelection(viewHolder.et.getText().length());
}
}
??最后在onBindViewHolder方法中,綁定數(shù)據(jù)與焦點切換時的監(jiān)聽就行了
@Override
public synchronized void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {
final int position = i;
ItemHolder viewHolder = (ItemHolder) holder;
viewHolder.tv.setText("item "+position);
viewHolder.et.setText(etTextAry.get(position));
viewHolder.et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean b) {
if (b){
//記錄焦點位置
etFocusPos = position;
}
}
});
}
四 結(jié)束語
希望以上的完整DEMO和代碼的講解能幫您解決這些小問題