2013-10-29 25 views
4

因此,我有一個自定義適配器,每行都有兩個EditText字段。EditText在列表適配器中,如何保存該值?

我已經得到了大部分的東西正常工作,除了保存在ArrayList中的值。

這是代碼我迄今所做的:

private void holderTitleSavedOnScroll(final int position, IZUICartViewHolder holder) { 
    if (!(position == (variantArrayList.size() - 1)) && holder.title != null) { 
     holder.title.setText(variantArrayList.get(position).getVariantTitle()); 
     final int finalPosition = position; 
     holder.title.setOnFocusChangeListener(new OnFocusChangeListener() { 
      @Override 
      public void onFocusChange(View v, boolean hasFocus) { 
        final EditText newVariant = (EditText) v; 
        variantArrayList.get(finalPosition).setVariantTitle(newVariant.getText().toString()); 
      } 
     }); 
    } 
} 

所以實際上我想要做什麼,這樣可以節省當焦點已經改變的值。除了一個問題,它只會在焦點改變時保存值。

除了當用戶實際按下使整個視圖消失的按鈕時,大多數情況下都很棒。焦點永遠不會改變,並且價值不會被設置。

所以我猜你是所有的思想,是我們只需要調用addOnTextChangedListener並附加TextWatcher,加入這樣的事情:

 holder.title.setText(variantArrayList.get(position).getVariantTitle()); 
     final int finalPosition = position; 
     final EditText holderTitle = (EditText) holder.title; 

     if (holderTitle.getTag() != null) { 
      final 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) { 
         variantArrayList.get(finalPosition).setVariantTitle(s.toString()); 
       } 

       @Override 
       public void afterTextChanged(Editable s) { 

       } 
      }; 


      holder.title.addTextChangedListener(textWatcher); 
      holder.title.setTag(true); 
     } 

不,這不會工作。 確定它實際上保存了值,但它也會在滾動時混淆東西,因爲listview重用了它認爲它來自一個單元格的值在另一個單元格中的值,然後從ArrayList中設置該值。

我已經嘗試了不同的東西,如更改值和東西時檢查焦點,但它不起作用(或多或少顯而易見的原因)。

有沒有創造性的解決方案來解決這個問題?

UPDATE(隨着越來越多的代碼):

的TextWatcher方法的建議:

我getView方法(很多其他不相關的代碼,這個問題在這裏):

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View v = convertView; 
    IZUICartViewHolder holder; 
    LayoutInflater inflater = ((Activity) context).getLayoutInflater(); 

    if (v == null) { 

     holder = new IZUICartViewHolder(); 
     int type = getItemViewType(position); 

     switch (type) { 
      case TYPE_EDIT: 
       v = inflater.inflate(R.layout.iz_ui_modify_product_cell, parent, false); 
       holder.title = (EditText) v.findViewById(R.id.iz_prod_modify_variant_title); 
       holder.title.setHint(addVariantPlaceholder); 
       holder.deleteButton = v.findViewById(R.id.click_remove); 
       holder.price = (EditText) v.findViewById(R.id.iz_prod_modify_price); 
       holder.price.setHint(pricePlaceholder); 
       holder.price.setText(String.valueOf(0.0)); 
       break; 

     } 

     v.setTag(holder); 

    } else { 
     holder = (IZUICartViewHolder) v.getTag(); 
    } 

    hideDeleteButton(holder, position); 
    holderTitleSavedOnScroll(position, holder); 
    holderPriceSavedOnScroll(position, holder); 

    v.setTag(holder); 
    return v; 
} 

holderTitleSavedOnScroll方法

private void holderTitleSavedOnScroll(final int position, IZUICartViewHolder holder) { 
    if (!(position == (variantArrayList.size() - 1)) && holder.title != null) { 

     holder.title.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       v.requestFocus(); 
      } 
     }); 


     final int finalPosition = position; 
     final EditText holderTitle = (EditText) holder.title; 

     if (holderTitle != null) { 
      holder.title.setText(variantArrayList.get(position).getVariantTitle()); 
     } 

     holderTitle.addTextChangedListener(new EditVariantTextWatcher(variantArrayList.get(finalPosition))); 

    } 
} 

的TextWatcher類:

public class EditVariantTextWatcher implements TextWatcher { 

private IZUIProductVariantContainer variantContainer; 

protected EditVariantTextWatcher(IZUIProductVariantContainer variantContainer) { 
    this.variantContainer = variantContainer; 
} 

@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) { 
    variantContainer.setVariantTitle(s.toString()); 
} 
} 
+0

您是否刪除了任何現有的TextWatcher? – blahdiblah

+0

試過了,沒有工作。 –

回答

6

這可以通過小心使用TextWatchers來完成。

在您的ViewHolder中包含對當前TextWatcher的引用。當視圖被回收時,刪除現有的TextWatcher並添加一個新的,鍵入當前位置。

這是一個完整的工作示例,包括狀態保存,以便測試導航遠:

public class EditTextListActivity extends ListActivity { 

    private static final String SAVED_STATE_KEY = "saved_state_key"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     EditTextAdapter editTextAdapter = new EditTextAdapter(this, R.layout.main); 
     setListAdapter(editTextAdapter); 

     // Restore our state, if there is any 
     if (savedInstanceState != null) { 
      List<String> savedStrings = savedInstanceState.getStringArrayList(SAVED_STATE_KEY); 
      for (String savedString : savedStrings) 
       editTextAdapter.add(new ListItem(savedString)); 
     } else { 
      // Add some empty items so that we can see it in action 
      for (int i = 0; i < 30; i++) 
       editTextAdapter.add(new ListItem("")); 
     } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     ArrayList<String> arrayList = new ArrayList<String>(); 
     EditTextAdapter editTextAdapter = (EditTextAdapter) getListAdapter(); 
     for (int i = 0; i < editTextAdapter.getCount(); i++) 
      arrayList.add(editTextAdapter.getItem(i).string1); 
     outState.putStringArrayList(SAVED_STATE_KEY, arrayList); 
    } 

    /** 
    * The object we have a list of, probably more complex in your app 
    */ 
    static class ListItem { 
     public String string1; 

     ListItem(String string1) { 
      this.string1 = string1; 
     } 
    } 

    /** 
    * ViewHolder which also tracks the TextWatcher for an EditText 
    */ 
    static class ViewHolder { 
     public TextView textView; 
     public EditText editText; 
     public TextWatcher textWatcher; 
    } 

    class EditTextAdapter extends ArrayAdapter<ListItem> { 
     EditTextAdapter(Context context, int resource) { 
      super(context, android.R.layout.simple_list_item_single_choice); 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
      View rowView = convertView; 
      if (rowView == null) { 
       // Not recycled, inflate a new view 
       rowView = getLayoutInflater().inflate(R.layout.main, null); 
       ViewHolder viewHolder = new ViewHolder(); 
       viewHolder.textView = (TextView) rowView.findViewById(R.id.textview); 
       viewHolder.editText = (EditText) rowView.findViewById(R.id.edittext1); 
       rowView.setTag(viewHolder); 
      } 

      ViewHolder holder = (ViewHolder) rowView.getTag(); 
      // Remove any existing TextWatcher that will be keyed to the wrong ListItem 
      if (holder.textWatcher != null) 
       holder.editText.removeTextChangedListener(holder.textWatcher); 

      final ListItem listItem = getItem(position); 

      // Keep a reference to the TextWatcher so that we can remove it later 
      holder.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) { 
        listItem.string1 = s.toString(); 
       } 

       @Override 
       public void afterTextChanged(Editable s) { 
       } 
      }; 
      holder.editText.addTextChangedListener(holder.textWatcher); 

      holder.editText.setText(listItem.string1); 
      holder.textView.setText(Integer.toString(position)); 

      return rowView; 
     } 
    } 
} 

layout/main.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="horizontal"> 

    <TextView 
     android:id="@+id/textview" 
     android:layout_width="0dp" 
     android:layout_weight="1" 
     android:layout_height="wrap_content" /> 

    <EditText 
     android:id="@+id/edittext1" 
     android:layout_width="0dp" 
     android:layout_height="?android:attr/listPreferredItemHeightSmall" 
     android:layout_weight="2" 
     android:inputType="text" /> 

    <!-- This EditText is included to demonstrate problems with a naive approach. --> 
    <EditText 
     android:inputType="text" 
     android:layout_width="0dp" 
     android:layout_height="?android:attr/listPreferredItemHeightSmall" 
     android:layout_weight="2" /> 
</LinearLayout> 

已知的bug:當鍵盤出現一個EditText會失去最初的焦點,請參閱this answer討論該問題。

0

我們可以節省價值與TextWatcher

更好的幫助下,使用模型來存儲和檢索的EditText的值。

public class RowData { 

    private String value; 

    public String getValue() { 
     return value; 
    } 

    public void setValue(String value) { 
     this.value = value; 
    } 
} 

接下來是TextWatcher監聽

public class EditTextWatcher implements TextWatcher { 

    private RowData data; 

    public EditTextWatcher(RowData data) { 
     this.data = data; 
    } 

    @Override 
    public void afterTextChanged(Editable s) { 
     data.setValue(s.toString()); 
    } 

    @Override 
    public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, 
      int arg3) { 

    } 

    @Override 
    public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { 

    } 

} 

適配器類

  public class YourAdapter extends ArrayAdapter<RowData> { 
       private ArrayList<RowData> data; 
       private Context context; 
      public YourAdapter(Context context, ArrayList<RowData> data) { 
        super(context, 0, data); 
        this.data = data; 
       } 
      @Override 
      public View getView(final int position, View convertView, ViewGroup parent) { 
       View v = convertView; 
       final RowData row = data.get(position); 
       final EditText edittext = (EditText) v.findViewById(R.id.edittext); 
       if (edittext != null) 
        edittext.setText(row.getValue()); 
       edittext.addTextChangedListener(new EditTextWatcher(row)); 


       ///////Your Code 
       ///// 
     } 
} 

// edittext.addTextChangedListener(new EditTextWatcher(row));這條線將存儲 每個的EditText中的數據,並且即使您將在一段時間後滾動ListView創建單元格 它將設置值從模型(RowData)

試試這樣,希望這會幫助你。

+0

我無法得到這個工作,在滾動期間值變得混亂。每次重新使用新行時,都會觸發文本觀察者AfterTextChanged。有任何想法嗎? –

+0

@JoakimEngstrom你有沒有嘗試過我的方法?或分享您的完整適配器類或更新您的問題本身? –

+0

用你的方法更新了這個問題。還嘗試了一些修改,但仍然使用重複值設置值,因爲每當OS重新使用一行時觸發afterTextChanged。 –

相關問題