2011-06-07 29 views
34

我有一個ListView其中每行都有一個EditText控制。我想爲每行添加一個TextChangedListener;一個包含額外數據,說明哪一行是EditText。問題是,當getView被調用時,會添加多個TextWatchers;因爲convertView已經有一個TextWatcher(和一個指向不同的行)。如何刪除添加了addTextChangedListener的所有聽衆

MyTextWatcher watcher = new MyTextWatcher(currentQuestion); 
EditText text = (EditText)convertView.findViewById(R.id.responseText); 
text.addTextChangedListener(watcher); 

MyTextWatcher是我的班級,實施TextWatcher;並處理文本事件。 CurrentQuestion讓我知道我正在執行哪一行。當我輸入框中時;調用TextWatcher的多個實例。

有沒有什麼辦法在添加新的之前刪除TextWatchers?我看到removeTextChangedListener方法,但這需要傳入一個特定的TextWatcher,我不知道如何獲得已經存在的TextWatcher的指針。

+2

對於所有元素只有一個TextWatcher會不會更簡單? – Jodes 2011-06-07 19:41:06

+1

如何在文本更改方法觸發時知道哪一行被修改? – GendoIkari 2011-06-07 19:48:47

+1

@Jodes:我不認爲最好有一個TextWatcher適用於所有元素。如果你想添加/刪除它們,你需要不同的textwatchers。 – 2012-04-18 12:15:25

回答

28

直接使用接口EditText沒有辦法做到這一點。我看到了兩個可能的解決方案:

  1. 重新設計應用程序讓你隨時知道TextWatcher被添加到特定的EditText實例。
  2. 延伸EditText並增加清除所有觀察者的可能性。

下面是第二種方法的例子 - ExtendedEditText

public class ExtendedEditText extends EditText 
{ 
    private ArrayList<TextWatcher> mListeners = null; 

    public ExtendedEditText(Context ctx) 
    { 
     super(ctx); 
    } 

    public ExtendedEditText(Context ctx, AttributeSet attrs) 
    { 
     super(ctx, attrs); 
    } 

    public ExtendedEditText(Context ctx, AttributeSet attrs, int defStyle) 
    {  
     super(ctx, attrs, defStyle); 
    } 

    @Override 
    public void addTextChangedListener(TextWatcher watcher) 
    {  
     if (mListeners == null) 
     { 
      mListeners = new ArrayList<TextWatcher>(); 
     } 
     mListeners.add(watcher); 

     super.addTextChangedListener(watcher); 
    } 

    @Override 
    public void removeTextChangedListener(TextWatcher watcher) 
    {  
     if (mListeners != null) 
     { 
      int i = mListeners.indexOf(watcher); 
      if (i >= 0) 
      { 
       mListeners.remove(i); 
      } 
     } 

     super.removeTextChangedListener(watcher); 
    } 

    public void clearTextChangedListeners() 
    { 
     if(mListeners != null) 
     { 
      for(TextWatcher watcher : mListeners) 
      { 
       super.removeTextChangedListener(watcher); 
      } 

      mListeners.clear(); 
      mListeners = null; 
     } 
    } 
} 

這裏是你如何在XML佈局中使用ExtendedEditText

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

    <ua.inazaruk.HelloWorld.ExtendedEditText 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:text="header" 
     android:gravity="center" /> 

</LinearLayout> 
+1

打我吧:) – icyerasor 2011-06-07 19:40:21

0

正如你可以在這裏看到:CodeSearch of TextView有是沒有辦法刪除所有的聽衆。唯一的辦法是提供你用來註冊的觀察者。

我還沒有完全理解爲什麼還有其他聽衆已經註冊。但是,您可以繼承EditText的子類,重寫addTextChangedListener(..),並在其中保留所有添加的引用的副本,然後委派給超類實現。然後您還可以提供一個刪除所有偵聽器的附加方法。

保持聯繫,如果您需要進一步的解釋。

+0

如果你是在一個匿名的內部類中,你如何提供一個註冊的觀察者? – 2012-04-18 00:28:38

12

您可以從EditText中刪除TextWatcher。首先,我建議你移動TextWatcher聲明的editText.addTextChangedListener(...)以外:

protected TextWatcher yourTextWatcher = new TextWatcher() { 

    @Override 
    public void afterTextChanged(Editable s) { 
     // your logic here 
    } 

    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
     // your logic here 
    } 

    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) { 
     // your logic here 
    } 
}; 

之後,你將能夠設定TextWather有點簡單:

editText.addTextChangedListener(yourTextWatcher); 

比你可以像這樣刪除TextWatcher:

editText.removeTextChangedListener(yourTextWatcher); 

並設置另一個如果你想。

+0

但這意味着您必須知道應用於您的EditText的確切textWatcher名稱。我相信問題是如何刪除EditText上的所有textWatcher。 – 2016-01-25 15:13:51

+0

Igor Ganapolsky你是對的。但在許多其他情況下,這是一個非常有用的東西 – 2016-05-31 16:34:36

6

將當前的textwatcher保存在viewholder中,您可以找到想要刪除的文本。

7

我也花了很多時間找到解決方案,最終最終解決了像下面這樣的標籤。 它將通過從convertView的標記獲取引用來刪除先前的TextWatcher實例。 它完美地解決了這個問題。 在你CustomAdapter文件中,設置一個新的內部類象下面這樣:

private static class ViewHolder { 

     private TextChangedListener textChangedListener; 
     private EditText productQuantity; 

     public EditText getProductQuantity() { 
      return productQuantity; 
     }  

     public TextChangedListener getTextChangedListener() { 
      return textChangedListener; 
     } 

     public void setTextChangedListener(TextChangedListener textChangedListener) { 
      this.textChangedListener = textChangedListener; 
     } 
    } 

然後在你的overrided公共查看getView(INT位置,查看convertView,一個ViewGroup父)方法執行類似下面的邏輯:

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

    EditText productQuantity; 
    TextChangedListener textChangedListener; 

    if(convertView==null) { 
     LayoutInflater mInflater = (LayoutInflater) 
       context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); 
     convertView = mInflater.inflate(R.layout.cart_offer_item, parent, false); 

     productQuantity=(EditText)convertView.findViewById(R.id.productQuantity); 
     addTextChangedListener(viewHolder, position); 
     convertView.setTag(viewHolder); 
    } 
    else 
    { 
     ViewHolder viewHolder=(ViewHolder)convertView.getTag(); 
     productQuantity=viewHolder.getProductQuantity(); 
     removeTextChangedListener(viewHolder); 
     addTextChangedListener(viewHolder, position); 
    } 

    return convertView; 
} 



private void removeTextChangedListener(ViewHolder viewHolder) 
{ 
    TextChangedListener textChangedListener=viewHolder.getTextChangedListener(); 
    EditText productQuantity=viewHolder.getProductQuantity(); 
    productQuantity.removeTextChangedListener(textChangedListener); 
} 

private void addTextChangedListener(ViewHolder viewHolder, int position) 
{ 
    TextChangedListener textChangedListener=new TextChangedListener(position); 
    EditText productQuantity=viewHolder.getProductQuantity(); 
    productQuantity.addTextChangedListener(textChangedListener); 
    viewHolder.setTextChangedListener(textChangedListener); 
} 

然後實現如下TextWatcher類:

private class TextChangedListener implements TextWatcher 
{ 
    private int position; 
    TextChangedListener(int position) 
    { 
     this.position=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) { 
    Log.d("check", "text changed in EditText"); 

    } 
} 

這將通過獲取引用從標籤刪除以前的TextWatcher實例convertView

0

我所做的刪除文本觀察者非常簡單。我創建了一個數組把我textwatchers:

final TextWatcher[] textWatchers = new TextWatcher[3]; 

我加入他們:

final int CURRENT_PIN_CHECK = 0, NEW_PIN = 1, CONFIRM_PIN_CHECK = 2; 

textWatchers[CURRENT_PIN_CHECK] = returnTextWatcherCheckPIN(CURRENT_PIN_CHECK); 
textWatchers[NEW_PIN] = returnTextWatcherCheckPIN(NEW_PIN); 
textWatchers[CONFIRM_PIN_CHECK] = returnTextWatcherCheckPIN(CONFIRM_PIN_CHECK); 

我returnTextWatcherCheckPIN方法實例用不同的檢查(switchMethod檢查所有四個editTexts)上afterTextChanged一個textWatcher。

然後,每當我刪除文本觀察家我只是引用該數組中的一個:

etPin4.removeTextChangedListener(textWatchers[CURRENT_PIN_CHECK]); 

檢查EDITTEXT的聽衆規模上調試:

enter image description here

它刪除!這解決了我的問題!

1

我曾與xamarin/C#同樣的問題,我寫了這個類來管理一個ListView內單擊事件在項目視圖將被「回收」:

public class ViewOnClickEventHandler: Java.Lang.Object 
{ 
    private List<EventHandler> EventList { get; set; } 

    public void SetOnClickEventHandler(View view, EventHandler eventHandler) 
    { 
     if (view.Tag != null) 
     { 
      ViewOnClickEventHandler holder = ((ViewOnClickEventHandler)view.Tag); 

      foreach (EventHandler evH in holder.EventList) 
       view.Click -= evH; 

      for (int i = 0; i < holder.EventList.Count; i++) 
       holder.EventList[i] = null; 

      holder.EventList.Clear(); 
     } 

     EventList = new List<EventHandler>(); 
     EventList.Add(eventHandler); 
     view.Click += eventHandler; 
     view.Tag = this; 
    } 
} 

您可以使用它你ListView BaseAdapter GetItem方法:

 TextView myTextView = convertView.FindViewById<TextView>(Resource.Id.myTextView); 

     ViewOnClickEventHandler onClick = new ViewOnClickEventHandler(); 
     onClick.SetOnClickEventHandler(myTextView, new EventHandler(delegate (object sender, EventArgs e) 
     { 
      // Do whatever you want with the click event 
     })); 

ViewOnClickEventHandler類將關心您的textview上的多個事件。您也可以更改textchange事件的類。這是相同的原理。 我希望這會有所幫助。

再見, nxexo007

0

我解決,而擴展的TextView類這種情況。

private ArrayList<TextWatcher> mEditTextWatcherList = new ArrayList<>(); 
private TextWatcher mTextWatcher1; 
private TextWathcer mTextWatcher2; 

mTextWathcer1 = 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) {} 

    @Override 
    public void afterTextChanged(Editable s) {} 
}; 

mTextWathcer2 = 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) {} 

    @Override 
    public void afterTextChanged(Editable s) {} 
}; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity); 

    setListener(mTextWatcher1); 
    setListener(mTextWatcher2); 

    removeListeners(); 
} 

private setListener(TextWatcher listener) { 
    mEditText.addTextChangedListener(listener); 
    mEditTextWatcherList.add(listener); 
} 

private removeListeners() { 
    for (TextWatcher t : mEditTextWatcherList) 
     mEditText.removeTextChangedListener(t); 

    mEditTextWatcherList.clear(); 
}