2014-01-06 32 views
7

我一直在尋找對此的答案,但解決方案似乎不適用於我。我在列表項中有一個TextView和一個EditText。我正嘗試在用戶編輯EditTexts時更新存儲的值。ListView中的EditText在滾動時由onTextChanged更新

@Override 
public View getView(int index, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    final int pos = index; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.user_details_list_row, parent,false); 
     holder = new ViewHolder(); 
     holder.mCaptionTextView = (TextView)convertView.findViewById(id.user_detail_row_caption); 
     holder.mDetailEditText = (EditText)convertView.findViewById(id.user_detail_row_value); 
     convertView.setTag(holder); 
    }else{ 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    holder.mDetailEditText.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
     } 

     @Override 
     public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void afterTextChanged(Editable s) {    
      mUserDetails.set(pos, s.toString()); 
     } 
    });  

    holder.mCaptionTextView.setText(mUserCaptions.get(index)); 
    holder.mDetailEditText.setText(mUserDetails.get(index),BufferType.EDITABLE); 

    return convertView; 
} 

public static class ViewHolder{ 
    public TextView mCaptionTextView; 
    public EditText mDetailEditText; 
} 

當我這樣做,滾動觸發TextWatcher並更新值,覆蓋從其他EditTexts的一個重複文本正確的文本。

取而代之的是TextWatcher的,我也嘗試過這樣的代碼:

holder.mDetailEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 

@Override 
public void onFocusChange(View v, boolean hasFocus) { 
    if (!hasFocus){ 
     EditText et = (EditText)v.findViewById(id.user_detail_row_value); 
     mUserDetails.set(index, et.getText().toString().trim()); 
    } 
} 
}); 

而且它還更新了錯誤的EditTexts。我在這裏錯過了什麼?

編輯:也試過這樣:

 final ViewHolder testHolder = holder; 
    holder.mDetailEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 

     @Override 
     public void onFocusChange(View v, boolean hasFocus) { 
      if (!hasFocus){ 
       EditText et = (EditText)v.findViewById(id.user_detail_row_value); 
       mUserDetails.set(testHolder.ref, et.getText().toString().trim()); 
      } 
     } 
    }); 

它糾正滾動變化問題我所看到的,但現在編輯EditTexts之一後,它改變了一堆其他的爲好。

回答

2

檢查您的索引值,如果它與您正在處理的行位置相匹配。如果您使用持有人模式,那麼取決於您的屏幕大小,可能該值不會從0更改爲7-8。像我這樣的事發生過一次,我想我通過實施getCount方法解決了這個問題。這樣行50給了我的位置50而不是7(例如)。

+0

我確實已經實現了getCount。它正在返回數據的大小,所以應該沒問題。 –

+0

哦,我看到了,我認爲問題可能是您在'onFocusChange'函數中設置的索引值。無論何時,您都可以使用'setTag'方法設置EditText的值,並嘗試設置其索引。然後在你的'onFocusChange'方法中使用'getTag'方法恢復它。 – zozelfelfo

+0

好的,將編輯索引添加到EditText本身就解決了整個問題。謝謝。 –

32

該問題與您未從EditText窗口小部件中刪除先前添加的文本查看器有關。相反,你不斷追加新的觀察者到列表中。一旦您嘗試編輯小部件內容,所有文本觀察者都會按順序收到通知,導致更新錯誤的用戶詳細信息。

EditText/TextView不提供刪除先前添加的文本觀察器的方法,而不需要爲他們設置explicit reference。這意味着您必須重新編寫代碼以保持對文本觀察者的引用,併爲每個getView方法執行創建/添加/刪除觀察者,或者擴展TextWatcher,以便在用戶更改後更新用戶詳細信息。後者在下面實施。

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ViewHolder holder = null; 
    if (convertView == null) { 
     convertView = mInflater.inflate(R.layout.user_details_list_row, parent,false); 
     holder = new ViewHolder(); 
     holder.mCaptionTextView = (TextView)convertView.findViewById(id.user_detail_row_caption); 
     holder.mWatcher = new MutableWatcher(); 
     holder.mDetailEditText = (EditText)convertView.findViewById(id.user_detail_row_value); 
     holder.mDetailEditText.addTextChangedListener(holder.mWatcher); 
     convertView.setTag(holder); 
    } else{ 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    holder.mCaptionTextView.setText(mUserCaptions.get(position)); 

    holder.mWatcher.setActive(false); 
    holder.mDetailEditText.setText(mUserDetails.get(position),BufferType.EDITABLE); 
    holder.mWatcher.setPosition(position); 
    holder.mWatcher.setActive(true); 

    return convertView; 
} 

static class ViewHolder{ 
    public TextView mCaptionTextView; 
    public EditText mDetailEditText; 
    public MutableWatcher mWatcher; 
} 

class MutableWatcher implements TextWatcher { 

    private int mPosition; 
    private boolean mActive; 

    void setPosition(int position) { 
     mPosition = position; 
    } 

    void setActive(boolean active) { 
     mActive = active; 
    } 

    @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) { 
     if (mActive) { 
      mUserDetails.set(mPosition, s.toString()); 
     } 
    } 
} 

希望這會有所幫助。

+1

這工作真的很好,很好的解釋。 – Charx

+0

這確實有效,我認爲這是最好的答案 –