2012-02-24 76 views
5

仍然是新的android和更多的自定義遊標適配器,所以我無法理解如何防止從列表視圖回收視圖,以防止輸入從一個編輯文本滾動顯示在另一個。我在其他帖子上看到說要更改convertview的名稱,但是如何做到這一點我正在畫空白。我希望這裏的某個人能夠根據我迄今爲止編寫的代碼提供更多細節或示例。EditText在ListView沒有它回收輸入

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; 

    } 

} 

改成了

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()); 
      } 

但回收所有的EditText後都有數據。嘗試使用holder.edittext.setText(oldText),但效果相同。

Start filling in fields

Finish filling in fields

Scroll up.

回答

4

首先,你真的不想要阻止列表視圖,從回收的意見。查看回收是一個巨大的優化。對於列表中的很多非常好的信息,請參閱google IO talk:http://www.youtube.com/watch?v=wDBM6wVEO70

這就是說,您已正確識別您的問題:您的EditTexts數量遠遠少於列表中的項目。當你在列表中滾動時,那些EditTexts會被回收,所以你會一次又一次地看到相同的輸入。

基本上你需要做的是在一些數據結構中保存你的EditTexts的輸入(一個HashMap,如果他們只編輯幾個值,可能是一個List,如果他們將改變大部分值,或者會工作)將位置映射到輸入。您可以通過在getView加入textChangedListener您在編輯文本做到這一點:

@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; 
} 

當用戶完成編輯,你可以通過你的數據結構運行,並盡一切與這些值。

編輯:

我改變onTextChanged到afterTextChanged因爲我之前使用的,我知道它的工作原理。請記住,afterExtChanged在每次LETTER更改時調用,而不僅僅是在用戶完成輸入單詞之後。如果用戶輸入「dog」後,文字變換將被調用三次,首先用'd',然後用'do',然後用'dog'調用。

HashMap很簡單:Map yourMapOfPositionsToValues = new HashMap();

添加或更新項目:yourMap.put(position,someText); 獲取一個項目:yourMap.get(position);

如果hashmaps沒有意義,花一些時間研究它們。它們是一個非常重要的數據結構。

您的TextWatcher實現不正確。您的數據結構不應該屬於單個視圖,而應該屬於活動或適配器。看起來你的職位並不穩定,因爲你的列表是由每個視圖所擁有。位置本身是穩定的,除非底層數據發生變化,光標將每次返回相同位置的相同數據。但是,編輯文本用於多個不同的位置。

創建一個hashmap作爲我在上面演示的適配器的構造函數中演示的一個實例變量。然後添加我最初寫的TextWatcher,不需要命名類,匿名更簡單。你的代碼應該工作。

+0

我正在玩aftertextchange,但我發現它沒有存儲我想要的值。 IE它只將部分字符串存儲到數組的不同部分。我可以在最後一個編輯文本中輸入類似狗的東西,以及何時調用ArrayList editTextList中的位置。它看起來像pos1狗pos2做pos3做的。我不明白爲什麼它只抓取edittext字符串的一部分。 – maebe 2012-02-25 05:38:31

+0

職位似乎不可靠,但也許我把他們稱爲錯誤的。當我使用simplecursor適配器時,我通過for循環更改了edittext的id,並使用該循環在下一個活動中存儲和調用它們。但仍遇到回收問題。過去兩週我一直在關注hashmaps,但似乎無法找到解釋如何使用它們的好消息。只有一點點的代碼在這裏和那裏。 – maebe 2012-02-25 05:38:54

+0

// TextWatcher,將數據保存到數組以備後用。 class watcher實現TextWatcher {0}私有int位置; public watcher(int position){this.position = position; } \t公共無效afterTextChanged(可編輯或多個){ \t \t \t \t \t \t \t \t \t \t \t \t \t \t \t Log.e(將String.valueOf(位置) 「是位置INT」) ; \t String text = s.toString(); \t editview.editTextList.add(position,text); 是我想到了我的textwatcher – maebe 2012-02-25 05:39:19

1

解決方法是在設置文本之前刪除添加的textwatcher。否則,該視圖上的以前的textwatcher將與新的textwatcher一起被調用。將textwatcher作爲標籤存儲在EditText上以跟蹤它。

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);