TextWatcher для более чем одного EditText - PullRequest
64 голосов
/ 26 ноября 2010

Я хочу реализовать интерфейс TextWatcher для нескольких полей EditText. В настоящее время я использую:

text1.addTextChangedListener(this);
text2.addTextChangedListener(this);

затем переопределяю методы в моей Деятельности:

public void afterTextChanged(Editable s) {}

public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) 
{
 // do some operation on text of text1 field
 // do some operation on text of text2 field 
}

Однако это работает нормально, но я ищу другие способы, чтобы я мог явно определить, в каком поле EditText находится фокус SoftKeyboard.

Ответы [ 14 ]

87 голосов
/ 09 декабря 2012

Предлагаемое решение в @ ответ Себастьяна Рота - это не один экземпляр TextWatcher для некоторых EditTexts. Это один класс и n экземпляров этого класса для n EditTexts.

Каждый EditText имеет свой Spannable. События TextWatcher имеют этот Spannable как параметр s. Я проверяю их hashCode (уникальный идентификатор каждого объекта). myEditText1.getText () возвращает этот Spannable. Так что если myEditText1.getText().hashCode() равно s.hashCode(), это означает, что s принадлежит myEditText1

Так что если вы хотите иметь один экземпляр TextWatcher для некоторых EditTexts, вы должны использовать это:

private TextWatcher generalTextWatcher = new TextWatcher() {    

    @Override
    public void onTextChanged(CharSequence s, int start, int before,
            int count) {

        if (myEditText1.getText().hashCode() == s.hashCode())
        {
            myEditText1_onTextChanged(s, start, before, count);
        }
        else if (myEditText2.getText().hashCode() == s.hashCode())
        {
            myEditText2_onTextChanged(s, start, before, count);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {

        if (myEditText1.getText().hashCode() == s.hashCode())
        {
            myEditText1_beforeTextChanged(s, start, count, after);
        }
        else if (myEditText2.getText().hashCode() == s.hashCode())
        {
            myEditText2_beforeTextChanged(s, start, count, after);
        }
    }

    @Override
    public void afterTextChanged(Editable s) {
        if (myEditText1.getText().hashCode() == s.hashCode())
        {
            myEditText1_afterTextChanged(s);
        }
        else if (myEditText2.getText().hashCode() == s.hashCode())
        {
            myEditText2_afterTextChanged(s);
        }
    }

};

и

myEditText1.addTextChangedListener(generalTextWatcher);
myEditText2.addTextChangedListener(generalTextWatcher);
82 голосов
/ 26 ноября 2010

Я бы сделал это так:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    EditText e = new EditText(this);
    e.addTextChangedListener(new CustomTextWatcher(e));
}

private class CustomTextWatcher implements TextWatcher {
    private EditText mEditText;

    public CustomTextWatcher(EditText e) { 
        mEditText = e;
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    public void afterTextChanged(Editable s) {
    }
}
12 голосов
/ 24 декабря 2013

используя идею "CustomTextWatcher", я сделал это

1) Создал новый интерфейс TextWatcherListener:

public interface TextWatcherExtendedListener extends NoCopySpan
{
    public void afterTextChanged(View v, Editable s);

    public void onTextChanged(View v, CharSequence s, int start, int before, int count);

    public void beforeTextChanged(View v, CharSequence s, int start, int count, int after);
}

2) Создал и использовал EditTextExtended вместо EditText (в моем случае):

public class EditTextExtended extends EditText
{
   private TextWatcherExtendedListener  mListeners = null;

   public EditTextExtended(Context context) 
   {
     super(context);
   }

   public EditTextExtended(Context context, AttributeSet attrs)
   {
      super(context, attrs);
   }

   public EditTextExtended(Context context, AttributeSet attrs, int defStyle)
   {
        super(context, attrs, defStyle);
   }

   public void addTextChangedListener(TextWatcherExtendedListener watcher) 
   {    
       if (mListeners == null) 
       {
           mListeners = watcher;
       }
   }

   public void removeTextChangedListener(TextWatcherExtendedListener watcher) 
   {
       if (mListeners != null) 
       {
           mListeners = null;        
       }
   }

   void  sendBeforeTextChanged(CharSequence text, int start, int before, int after)
   {
       if (mListeners != null) 
       {
           mListeners.beforeTextChanged(this, text, start, before, after);
       }
   }

   void  sendOnTextChanged(CharSequence text, int start, int before,int after) 
   {
       if (mListeners != null) 
       {
           mListeners.onTextChanged(this, text, start, before, after);
       }
   }

   void  sendAfterTextChanged(Editable text) 
   {
       if (mListeners != null)
       {
           mListeners.afterTextChanged(this, text);
       }
   }
}

3) Итак, где вам нужно написать этот код:

myEditTextExtended.addTextChangedListener(this) //Let implement TextWatcherExtendedListener methods

4) использовать их:

@Override
public void onTextChanged(View v, CharSequence s, int start, int before, int count) 
{
   //Tested and works
   //do your stuff  
}


@Override
public void beforeTextChanged(View v, CharSequence s, int start, int count, int after)
{   
     //not yet tested but it should work    
}

@Override
public void afterTextChanged(View v, Editable s) 
{
    //not yet tested but it should work 
}

Ну, дайте мне знать, что делатьвы думаете.

11 голосов
/ 18 июня 2014

- РЕДАКТИРОВАТЬ -

Если вы хотите использовать только после TextChanged, сравните редактируемые:

@Override
public void afterTextChanged(Editable editable) {
    if (editable == mEditText1.getEditableText()) {
        // DO STH
    } else if (editable == mEditText2.getEditableText()) {
        // DO STH
    }
}
7 голосов
/ 10 марта 2017

Я использую это решение:

  • Добавить метод, который возвращает слушателя:

    private TextWatcher getTextWatcher(final EditText editText) {
        return new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
            }
    
            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                // do what you want with your EditText
                editText.setText("blabla");
            }
    
            @Override
            public void afterTextChanged(Editable editable) {
    
            }
        };
    }
    
  • Добавить слушателя к нескольким EditText, вы также можетепередать другие параметры:

    editText1.addTextChangedListener(getTextWatcher(editText1));
    editText2.addTextChangedListener(getTextWatcher(editText2));
    editText3.addTextChangedListener(getTextWatcher(editText3));
    
2 голосов
/ 12 мая 2014

Еще один способ - добавить OnClickListener к EditText и установить глобальную переменную, как указано ниже

EditText etCurrentEditor;//Global variable

@Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        if(v instanceof EditText){
            etCurrentEditor=(EditText)v;
        }
    }

Используйте этот etCurrentEditor как ссылку на редактируемый в данный момент EditText

@Override
    public void afterTextChanged(Editable editable) {
        // TODO Auto-generated method stub
        switch (etCurrentEditor.getId()) {
        case R.id.EDITTEXTID:
            break;
        default:
            break;
        }
    }
1 голос
/ 10 октября 2017

Попробовав несколько способов добиться этого, я нашел правильный путь, используя EditText.isFocused(), чтобы различать одно от другого.Например:

    private class OnTextChangedListener implements TextWatcher {

    @Override
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

    }

    @Override
    public void afterTextChanged(Editable editable) {
        if (edtName.isFocused()) {
            //do something
        } else if (edtEmail.isFocused()) {
            //do something
        } else if (edtContent.isFocused()) {
             //do something
        }
    }
}
1 голос
/ 28 февраля 2017

Я реализовал это как:

edittext1.addTextChangedListener(this);
edittext2.addTextChangedListener(this);
edittext3.addTextChangedListener(this);

и

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    if(edittext1.hasFocus()){
        //text changed for edittext1
    }else if(edittext2.hasFocus()){
        //text changed for edittext2
    }else {
        //text changed for edittext3
    }
}

@Override
public void afterTextChanged(Editable editable) {

}
1 голос
/ 15 октября 2013

Global Один класс для всех видов деятельности.

CustomTextWatcher.java

package org.logicbridge.freshclub.customizedItems;

import android.content.Context;
import android.text.Editable;
import android.text.TextWatcher;
    public class CustomTextWatcher implements TextWatcher {
        private EditText mEditText;
        Context context;

        public CustomTextWatcher(EditText e, Context context) {
            mEditText = e;
            this.context = context;
        }

        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        public void afterTextChanged(Editable s) {

        }
    }
1 голос
/ 12 мая 2013

Да, вы можете использовать несколько экземпляров пользовательского TextWatcher, в котором хранится TextView.(TextView на самом деле является классом, который имеет addTextChangedListener.)

Подобно приведенному выше решению hashCode, вы можете просто проверить, если getText()==s.Вместо того, чтобы хранить все свои элементы управления или findViewById несколько раз, вы можете просто один раз отсканировать дерево контента на наличие элемента управления, который имеет CharSequence.

public TextView findTextView(View v, CharSequence s)
{
   TextView tv;
   ViewGroup vg;
   int i, n;

   if (v instanceof TextView)
   {
      tv = (TextView) v;
      if (tv.getText()==s) return(tv);
   }

   else if (v instanceof ViewGroup)
   {
      vg = (ViewGroup) v;
      n = vg.getChildCount();
      for(i=0;i<n;i++)
      {
         tv = findTextView(vg.getChildAt(i), s);
         if (tv!=null) return(tv);
      }
   }

   return(null);
}

public void afterTextChanged(Editable s)
{
   TextView tv=findTextView(findViewById(android.R.id.content), s);
   if (tv==null) return;
   switch(tv.getId())
   {
      case R.id.path:
         break;
      case  R.id.title:
         break;
   }
}

Конечно, вы также можете использовать findTextView внутри beforeTextChanged и onTextChanged.

...