2013-10-29 2 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); 
     } 

아니, 하나가 작동하지 않을 것이다. 물론 값을 실제로 저장하지만 목록보기에서 셀을 다시 사용하기 때문에 스크롤하면 내용이 엉망이됩니다. 한 셀의 값이 다른 셀에 있다고 가정하고 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

기존 TextWatchers를 제거 하시겠습니까? – blahdiblah

+0

시도했지만 작동하지 않았습니다. –

답변

6

이것은 TextWatchers를주의해서 사용할 수 있습니다.

현재 TextWatcher에 대한 참조를 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> 

알려진 버그 : 키보드가 온다 때 글고 초기 초점을 잃게됩니다 , 해당 문제에 대한 설명은 this answer을 참조하십시오.

0

우리는 저장하고 글고의 값을 검색 할 수있는 모델을 사용하는 TextWatcher

더 나은의 도움으로 값을 절약 할 수 있습니다.

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)); 각 글고 치기에 대한 데이터 및 경우에도 저장됩니다이 줄 ListView를 스크롤 한 다음 셀을 생성하는 경우 Model (RowData)에서 값을 설정합니다

이렇게하면 도움이 될 것입니다.

+0

이 작업을 수행 할 수 없으며 스크롤하는 동안 값이 엉망이됩니다. 텍스트 워처 AfterTextChanged는 새 행이 다시 사용될 때마다 트리거됩니다. 어떤 아이디어? –

+0

@JoakimEngstrom 내 접근 방식으로 시도해 봤어? 또는 전체 어댑터 클래스를 공유하거나 질문 자체를 업데이트 할 수 있습니까? –

+0

이 귀하의 접근 방식으로 질문을 업데이트했습니다. 또한 몇 가지 수정을 시도해 보았지만, afterTextChanged는 os가 행을 재사용 할 때마다 트리거되므로 값은 재사용 된 값으로 설정됩니다. –

관련 문제