2012-02-24 10 views
5

Wciąż nowy dla Androida, a jeszcze bardziej dla niestandardowego adaptera kursora, więc mam problem ze zrozumieniem, jak zapobiec wyświetlaniu widoków z list odtwarzania, aby zapobiec wprowadzaniu jednego tekstu editekstowego do innego podczas przewijania. Widziałem w innym poście mówiącym o zmianie nazwy konwersji, ale jak to zrobić, rysuję puste miejsce. Miałem nadzieję, że ktoś tutaj będzie mógł podać więcej szczegółów lub przykład tego, jak to zrobić w oparciu o kod, który napisałem do tej pory.EditText in ListView bez wprowadzania danych do recyklingu

public class editview extends ListActivity { 
    private dbadapter mydbhelper; 
    private PopupWindow pw; 
    public static int editCount; 
    public static ListView listView; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mydbhelper = new dbadapter(this); 
     mydbhelper.open(); 


     View footer = getLayoutInflater().inflate(R.layout.footer_layout, null); 
     ListView listView = getListView(); 
     listView.addFooterView(footer); 
     showResults(); 
     } 

    //Populate view 
    private void showResults(){ 
     Cursor cursor = mydbhelper.getUserWord(); 
     startManagingCursor(cursor); 
     String[] from = new String[] {dbadapter.KEY_USERWORD}; 
     int[] to = new int[] {R.id.textType}; 
     ItemAdapter adapter = new ItemAdapter(this, R.layout.edit_row, cursor, 
         from, to); 
      adapter.notifyDataSetChanged(); 
      this.setListAdapter(adapter); 
      editCount = adapter.getCount(); 

    } 


      //footer button 
      public void onClick(View footer){ 
        final MediaPlayer editClickSound = MediaPlayer.create(this, R.raw.button50); 
        editClickSound.start(); 
        startActivity(new Intent("wanted.pro.madlibs.OUTPUT")); 

       } 

//custom cursor adapter 
class ItemAdapter extends SimpleCursorAdapter { 
    private LayoutInflater mInflater; 
    private Cursor cursor; 


    public ItemAdapter(Context context, int layout, Cursor cursor, String[] from, 
      int[] to) { 
     super(context, layout, cursor, from, to); 
     this.cursor = cursor; 
     mInflater = LayoutInflater.from(context); 

    } 


    static class ViewHolder { 
     protected TextView text; 
     protected EditText edittext; 

    } 

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


     ViewHolder holder; 
     if (convertView == null) { 
      convertView = mInflater.inflate(R.layout.edit_row, null); 


      holder = new ViewHolder(); 
      holder.text = (TextView) convertView.findViewById(R.id.textType); 
      holder.edittext = (EditText) convertView.findViewById(R.id.editText); 



      convertView.setTag(holder); 

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

     } 
     cursor.moveToPosition(position); 
     int label_index = cursor.getColumnIndex("userword"); 
     String label = cursor.getString(label_index); 

     holder.text.setText(label); 

     return convertView; 

    } 

} 

Zmieniono go do

class ItemAdapter extends SimpleCursorAdapter { 
    private LayoutInflater mInflater; 
    private Cursor cursor; 
    Map<Integer, String> inputValues = new HashMap<Integer, String>(); 
    public View getView(final int position, View convertView, ViewGroup parent) { 
     .... 

     ViewHolder holder; 
     if (convertView == null) { 
      convertView = mInflater.inflate(R.layout.edit_row, null); 


      holder = new ViewHolder(); 
      holder.text = (TextView) convertView.findViewById(R.id.textType); 
      holder.edittext = (EditText) convertView.findViewById(R.id.editText); 


      convertView.setTag(holder); 

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

     } 
     cursor.moveToPosition(position); 
     int label_index = cursor.getColumnIndex("userword"); 
     String label = cursor.getString(label_index); 

     holder.text.setText(label); 
     String oldText = inputValues.get(position); 
     holder.edittext.setText(oldText == null ? "" : oldText); 
     holder.edittext.addTextChangedListener(new TextWatcher(){ 
      public void afterTextChanged(Editable editable) { 
       inputValues.put(position, editable.toString()); 
      } 

ale to jest recykling przecież EditText mieć dane. Próbowałem używając hold.edittext.setText (oldText), ale ten sam efekt.

Start filling in fields

Finish filling in fields

Scroll up.

Odpowiedz

4

Przede wszystkim, to naprawdę nie chcesz, aby zapobiec widoku listy z recyklingu swoje poglądy. Zobacz recykling to ogromna optymalizacja. Aby uzyskać wiele naprawdę dobrych informacji na listach, zobacz dyskusję Google na IO: http://www.youtube.com/watch?v=wDBM6wVEO70

W związku z tym prawidłowo zidentyfikowałeś swój problem: Masz znacznie mniej EditTextów niż na liście. Gdy przewijasz listę, te EditTexts są ponownie przetwarzane, więc wciąż widzisz te same dane wejściowe.

Zasadniczo konieczne jest zapisanie danych wejściowych dla plików EditText w niektórych strukturach danych (HashMap, jeśli edytują tylko kilka wartości, może Listę, jeśli będą zmieniać większość wartości, albo działały), odwzorowuje pozycję na dane wejściowe. Można to zrobić poprzez dodanie textChangedListener do edycji tekstów w getView:

@Override 
public View getView(final int position, View convertView, ViewGroup parent){ 
    ... 
    cursor.moveToPosition(position); 
    int label_index = cursor.getColumnIndex("userword"); 
    String label = cursor.getString(label_index); 

    holder.text.setText(label); 

    //clear whatever text was there from some other position 
    //and set it to whatever text the user edited for the current 
    //position if available 
    String oldText = yourMapOfPositionsToValues.get(position); 
    holder.setText(oldText == null ? "" : oldText); 

    //every time the user adds/removes a character from the edit text, save 
    //the current value of the edit text to retrieve later 
    holder.edittext.addTextChangedListener(new TextWatcher(){ 
     @Override 
     public void afterTextChanged(Editable editable) { 
      yourMapOfPositionsToValues.put(position, editable.toString()); 
     } 
     .... 
    }; 

    return convertView; 
} 

Gdy Twój użytkownik dokonuje edycji, można uruchomić za pośrednictwem datastructure i robić, co z tymi wartościami.

Edit:

Zmieniłem onTextChanged do afterTextChanged bo użyłem, że przed i wiem, że to działa. Należy pamiętać, że afterTextChanged jest wywoływane za każdym razem, gdy LETTER zmienia się, nie tylko po tym, jak użytkownik zakończy pisanie słowa. Jeśli użytkownik wpisze "pies" poTekstowej zmianie zostanie wywołany trzy razy, najpierw z "d", następnie z "do", a następnie z "psem".

HashMap jest prosty: zamapuj yourMapOfPositionsToValues ​​= new HashMap();

dodać lub zaktualizować element: yourMap.put (position, someText); , aby pobrać element: yourMap.get (pozycja);

jeśli nie ma sensu, poświęć trochę czasu na ich zbadanie. Są niewiarygodnie ważną strukturą danych.

Twoja implementacja TextWatchera jest niepoprawna. Struktura danych nie powinna należeć do pojedynczego widoku, ale raczej do działania lub adaptera. Wygląda na to, że pozycje nie są stabilne, ponieważ twoja lista jest własnością każdego widoku. Same pozycje są stabilne, chyba że zmieniają się dane, kursor zwróci te same dane za każdym razem dla tej samej pozycji. Jednak tekst edycji jest używany do wielu różnych pozycji.

Tworzenie HashMap jako instancja zmiennej I wykazano powyżej w konstruktorze adaptera. Następnie dodaj dokładnie TextWatcher, który napisałem oryginalnie, bez potrzeby używania nazwanej klasy, anonim jest prostszy. Twój kod powinien zadziałać.

+0

Grałem z aftertextchange, ale okazało się, że nie przechowywał wartości, jak chciałem. IE będzie przechowywać tylko część łańcucha w różnych częściach tablicy. Mógłbym wpisać coś takiego jak pies w ostatni edytor tekstu i kiedy wywoływałbym pozycje w ArrayList editTextList. Wyglądałoby to jak pos1 pos2 do pos3. Nie rozumiem, dlaczego to było tylko chwytanie części ciągu editekstowego. – maebe

+0

Pozycje wydawały się niewiarygodne, ale może nazwałem je niewłaściwymi. Kiedy używałem adaptera simplycursor, zmieniłem identyfikator edittext za pomocą pętli for i wykorzystywałbym tę pętlę do przechowywania i wywoływania ich przy następnym działaniu. Ale nadal napotykał problemy z recyklingiem. Przez ostatnie dwa tygodnie przyglądałem się problemom izhmaps, ale nie mogę znaleźć żadnych dobrych informacji wyjaśniających, jak z nich korzystać. Tylko fragmenty kodu tu i tam. – maebe

+0

// TextWatcher, zapisuje dane w Array do późniejszego wykorzystania. obserwator klasy implementuje TextWatcher { prywatna pozycja; obserwator publicznych (Int pozycja) { this.position = pozycja; } \t void afterTextChanged (edycji s) { \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t Log.e (String.valueOf (pozycja) „jest Int pozycji”) ; \t Tekst ciągu = s.toString(); \t editview.editTextList.add (położenie, tekst); Czy to, co ja przyszedłem z moim textwatcher – maebe

1

Rozwiązanie to jest usuwanie dodanej textwatcher przed ustawieniem tekstu. W przeciwnym razie poprzedni kontroler tekstu w tym widoku będzie nadal wywoływany wraz z nowym kontrolerem tekstów. Przechowuj textwatchera jako tag w EditText, aby go śledzić.

Object oldWatcher = viewHolder.quantitySold.getTag(); 
    if(oldWatcher != null){ 
     viewHolder.quantitySold.removeTextChangedListener((CustomTextWatcher)oldWatcher); 
    } 
    String oldText = inputValues.get("key"+position); 
    Log.d(TAG, "oldText: "+oldText+" position: "+position); 
    viewHolder.quantitySold.setText(oldText == null ? "" : oldText); 
    CustomTextWatcher watcher = new CustomTextWatcher(
      cursor.getString(SKUFragment.COL_NAME), 
      cursor.getInt(SKUFragment.COL_ID), 
      cursor.getDouble(SKUFragment.COL_UNIT_PRICE), 
      position 
    ) { 
     @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 (s != null) { 
       int quantity = 0; 
       if (!TextUtils.isEmpty(s.toString())) { 
        quantity = Integer.parseInt(s.toString()); 
        inputValues.put("key"+mPosition, "" + quantity); 
       }else{ 
        inputValues.put("key"+mPosition, ""); 
       } 
       double value = quantity * skuPrice; 
       mListener.onQuantityChanged(skuName+", position: "+mPosition, skuId, quantity, value); 
      } 
     } 
    }; 
    viewHolder.quantitySold.setTag(watcher); 
    viewHolder.quantitySold.addTextChangedListener(watcher); 
Powiązane problemy