2013-10-01 71 views
2

在我的項目中,我必須向用戶顯示基本上包含EditText的ListView。包含到Android ListView中的EditText的內容不會被保存

這就像一個問卷,當他回答他可以下來的問題,並回答下一個問題。 (恢復)

public class onAdapter extends BaseAdapter { 
    List<PointVerification> mObjects; 
    Context mContext; 
    LayoutInflater mInflater; 

    HashMap<Integer, List<ChoixPointVerification>> mChoix; 
    HashMap<Integer, ReponsePointVerification> mReponses; 
    HashMap<Integer, String> mReponsesActuel; 
    Integer mPositionSelectionne; 
    Integer mIdIntervention; 


    /** 
    * Constructeur 
    * @param context 

    * @param listePointsVerification Liste des points de vérification à afficher. 
    * @param listeChoixPointsVerification liste des choix de points de vérification pour chaque point de vérification. 
    * @param listeReponsesPointsVerification réponses déjà fournies pour chaque point de vérification 
    * @param idIntervention Identifiant de l'intervention 
    */ 
    public onAdapter(
      Context context, 

      Integer idIntervention, 
      List<PointVerification> listePointsVerification, 
      List<ChoixPointVerification>> listeChoixPointsVerification, 
      ReponsePointVerification> listeReponsesPointsVerification) { 

     this.mInflater = LayoutInflater.from(context); 
     this.mContext = context; 
     this.mObjects = listePointsVerification; 

     this.mChoix = listeChoixPointsVerification; 
     this.mReponses = listeReponsesPointsVerification; 
     this.mIdIntervention = idIntervention; 


     // préparation des réponses par position 
     this.mReponsesActuel = new HashMap<Integer, String>(); 
    } 


    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row; 

     final Integer idPointVerification = getItem(position).id; 

     if (convertView == null) 
     { 
      row = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, null); 

      EditText edValeur = (EditText) row.findViewById(R.id.edValeur); 
      // Ajout de l'évènement lorsque l'on change la valeur 
      // evènement d'enregistrement 
      edValeur.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) { 
        // This hashmap is a try workaround to the bug 
        // i register all modifications into this hashmap 
        mReponsesActuel.put(
          idPointVerification, 
          s.toString()); 

        // SAVE PROCEDURE 
        // REMOVED FOR THE EXAMPLE 
        // BUT I UPDATE MY DATABASE 
       } 
      }); 
     } 
     else 
     { 
      row = convertView; 
     } 

     EditText edValeur = (EditText) row.findViewById(R.id.edValeur); 

     // update of the text 
     // it is the contained in the hashmap 
     if (mReponsesActuel.containsKey(idPointVerification)) { 
      String valeur = mReponsesActuel.get(idPointVerification); 
      edValeur.setText(valeur); 
     // otherwhise i will look into the database 
     } else if (mReponses != null && mReponses.containsKey(idPointVerification) 
       && mReponses.get(idPointVerification).valeur != null) { 
      edValeur.setText(mReponses.get(idPointVerification).valeur); 
     } 
     else 
     { 
      edValeur.setText(""); 
     } 

     return row; 
    } 
} 

我不知道爲什麼,但用戶下井在ListView,內容是得救,顯示出與其他人一樣的EditText一些特殊的價值。我沒有找到如何糾正這種行爲,而且確實很匆忙。

基本上我做了一個TextWatcher,它將數據註冊到數據庫中,並將其轉換爲包含所有值的臨時HashMap。當調用GetView時,該數據被回調。如果我刪除了初始化,EditText被刪除。

注:我在我的代碼中做了一些測試,因此可能會有不同的問題。

編輯

我上傳的問題一個項目:http://dl.free.fr/rbqOhUfJF

下面的步驟來重現問題:

  1. 推出的項目在調試模式下

  2. 寫在第一行A,在第二個B,在第三個C

  3. 向下滾動,直到C被隱藏

  4. 滾動到頂部。結果:沒有更多文字。

如果仔細觀察調試日誌,您可以看到與afterText一致。每次我們在第2部分中寫入一些文本時,都會有一個調試行與註冊事件。

但在階段3,當你隱藏一個項目。活動將與「推出」

結果:在第四階段,它加載「」串

回答

5

要加快在大多數移動應用的東西(安卓iOS的...)列表的細胞通常回收。這爲特別針對長列表的備用內存。因此您必須獲取新顯示的單元格的數據。當單元格離開屏幕時,其佈局/視圖被破壞。在你的情況下,你必須在某處保存編輯文本的文本。這就是你想要用hashmap做的事情。

我在代碼中看不到任何特別的錯誤。

如果問題是關於使用hashmap的「解決方法」,我確認對我來說,由您來保存編輯文本的狀態。使用散列表是實現它的一種方式。

順便說一下,getItem(position).id可以用getItemId(position)來代替,這就是爲此目的。

不知道這一切是否回答你的問題。

編輯

現在,我明白你的問題正確,我可以提供一些代碼。我必須說,我對所找到的解決方案並不滿意,但至少它正在工作。

TextWatcher的問題是您無權訪問上下文和相應視圖。

使用setOnFocusChangeListener解決了這個問題。所以這裏是我終於工作的代碼。

public final class PointVerificationAdapter extends BaseAdapter { 
    List<BasicNameValuePair> mObjects; 
    Context mContext; 
    LayoutInflater mInflater; 
    HashMap<Integer, String> mReponsesActuel; 
    ArrayList<String> myItems = new ArrayList<String>(); 

    public PointVerificationAdapter(
      Context context, 
      List<BasicNameValuePair> listObjets 
      ) { 

     this.mInflater = LayoutInflater.from(context); 
     this.mContext = context; 
     this.mObjects = listObjets; 

     for (int i = 0; i < 30; i++) { 
      myItems.add(Integer.toString(i)); 
     } 
    } 

    @Override 
    public int getCount() { 
     return mObjects.size(); 
    } 

    @Override 
    public BasicNameValuePair getItem(int position) { 
     return mObjects.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    static class ViewHolder { 
     EditText yourEditText; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     ViewHolder holder = null; 

     if (convertView == null) 
     { 
      holder = new ViewHolder(); 
      convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false); 
      convertView.setId(position); 
      holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur); 

      convertView.setTag(holder); 
     } 
     else 
     { 
      holder = (ViewHolder) convertView.getTag(); 
     } 

     ((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position)); 

     holder.yourEditText.setText(myItems.get(position)); 
     holder.yourEditText.setId(position); 
     holder.yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() { 
      public void onFocusChange(View view, boolean hasFocus) { 
       if (!hasFocus){ 
        final int position = view.getId(); 
        final EditText editText = (EditText) view; 
        myItems.set(position, editText.getText().toString()); 
       } 
      } 
     }); 

     return convertView; 
    } 

} 

最後編輯

上面的代碼是工作,但我還是不滿意的話,因爲你問addTextChangedListener而不是onFocusChange

所以這裏是解決方案:

public final class PointVerificationAdapter extends BaseAdapter { 
    List<BasicNameValuePair> mObjects; 
    Context mContext; 
    LayoutInflater mInflater; 
    HashMap<Integer, String> mReponsesActuel; 
    ArrayList<String> myItems = new ArrayList<String>(); 

    public PointVerificationAdapter(
      Context context, 
      List<BasicNameValuePair> listObjets 
      ) { 

     this.mInflater = LayoutInflater.from(context); 
     this.mContext = context; 
     this.mObjects = listObjets; 

     for (int i = 0; i < 30; i++) { 
      myItems.add(Integer.toString(i)); 
     } 
    } 

    @Override 
    public int getCount() { 
     return mObjects.size(); 
    } 

    @Override 
    public BasicNameValuePair getItem(int position) { 
     return mObjects.get(position); 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    static class ViewHolder { 
     EditText yourEditText; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     ViewHolder holder = null; 

     if (convertView == null) 
     { 
      holder = new ViewHolder(); 
      convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false); 
      convertView.setId(position); 
      holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur); 
      holder.yourEditText.setId(position); 
      holder.yourEditText.addTextChangedListener(new GenericTextWatcher(holder.yourEditText)); 
      convertView.setTag(holder); 
     } 
     else 
     { 
      holder = (ViewHolder) convertView.getTag(); 
      holder.yourEditText.setId(position); 
     } 

     ((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position)); 

     holder.yourEditText.setText(myItems.get(position)); 

     return convertView; 
    } 

    private class GenericTextWatcher implements TextWatcher{ 

     private View view; 
     private GenericTextWatcher(View view) { 
      this.view = view; 
     } 

     public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} 
     public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} 

     public void afterTextChanged(Editable editable) { 
      final int position = view.getId(); 
      final EditText editText = (EditText) view; 
      myItems.set(position, editText.getText().toString()); 
     } 
    } 
} 
+1

它的工作原理,神奇的是與參考視圖GenericTextWatcher類? tks u很多 –

+3

是的,重點是正確訪問正確editText的視圖。在你的情況下,addTextChangedListener並不總是引用正確的editText。在這種情況下,你需要正確的上下文。通過將TextWatcher與'view'一起使用,我確信我已鏈接到正確的視圖,這是您正在編輯的editText之一。我必須承認,我努力尋找解決方案,但現在一切都清楚了。保重。見到 – HpTerm

+0

@HpTerm,非常感謝你的回答,顯然我使用ArrayAdapter和我的自定義數據類型,並且我無法將文本設置爲特定的editText,你能幫我理解我該如何獲取特定的editText閱讀信息,現在,我失去了edittext中的所有信息,或者他們被複制到其他edittext –