RecyclerView中解決EditText的各種異常

一 引言


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

二 效果圖(2.34 MB)


效果圖大小2.34 MB

三 解決方案


??因為有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和代碼的講解能幫您解決這些小問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,008評論 25 709
  • 一.常用控件的使用方法 1.TextView match_parent 由父布局來決定當(dāng)前控件的大小。wrap_c...
    努力生活的西魚閱讀 1,331評論 5 0
  • 世界上總會有一些善良單純的姑娘,但她們或許對自己是那么的不自信,她們認(rèn)為自己很丑很胖,平凡得不能再普通。她們總想藏...
    二三七閱讀 574評論 0 0
  • 九月,一個充滿希望的月份。大人們似乎都沉浸在豐收的喜悅里,在忙碌中滿足。但若是看看小孩子的世界,可真就是有些苦...
    摧毀敵方防御塔閱讀 385評論 1 2
  • 《歲月如歌》 文/白傳英 今夜我又想起了你 就像那過去 多想把你摟在懷里 親親遠(yuǎn)去的歲月 握住你的手 手心...
    白清風(fēng)閱讀 466評論 0 2

友情鏈接更多精彩內(nèi)容