TextWatcher для нескольких EditText
Я хочу реализовать интерфейс 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
.
- неявное vs явная реализация интерфейса
- Оператор «instanceof» ведет себя по-разному для интерфейсов и classов
- Абстрактный class в Java
- Интерфейсы наследуются от classа Object в java
- Являются ли значения по умолчанию в JDK 8 формой множественного наследования в Java?
- Интерфейс с методами по умолчанию vs Абстрактный class в Java 8
- Когда использовать интерфейс вместо абстрактного classа и наоборот?
- Как узнать, когда создавать интерфейс?
- Метод передачи Java в качестве параметра
- Java получает ошибку для реализации интерфейса с более слабым доступом
- Каковы различия между абстрактными classами и интерфейсами в Java 8?
- Как создать интерфейс между fragmentом и адаптером?
- Что означает «программа для интерфейсов, а не реализации»?
Предлагаемое решение в ответе @Sebastian Roth – это не один экземпляр TextWatcher
для некоторых EditTexts
. Это один class и n экземпляров этого classа для n EditTexts
.
Каждый EditText имеет свой собственный Spannable. TextWatcher
имеют этот параметр Spannable as 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);
Я бы сделал это так:
@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) { } }
используя идею «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 }
Ну, дайте мне знать, что вы думаете.
–РЕДАКТИРОВАТЬ–
Если вы хотите использовать только afterTextChanged, сравните редактируемые файлы:
@Override public void afterTextChanged(Editable editable) { if (editable == mEditText1.getEditableText()) { // DO STH } else if (editable == mEditText2.getEditableText()) { // DO STH } }
Я использую это решение:
-
Добавить метод, который возвращает слушатель:
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));
Еще один способ – добавить 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; } }
Да, вы можете использовать несколько экземпляров настраиваемого TextWatcher
которые хранят TextView
. ( TextView
на самом деле является classом с addTextChangedListener
.)
Подобно решению hashCode выше, вы можете просто проверить, есть ли getText()==s
. Вместо того, чтобы хранить все свои элементы управления или findViewById
несколько раз, вы можете просто сканировать дерево контента самостоятельно один раз для CharSequence
управления, который имеет 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
Конечно, вы также можете использовать findTextView
внутри beforeTextChanged
и onTextChanged
.
Global One для всех видов деятельности.
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) { } }
Я реализовал его как:
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) { }
Попробуйте несколько способов достичь этого, я найду правильный путь, используя 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 } } }
Вы всегда можете определить TextWatcher
как параметр addTextChangedListener
Таким образом, вы можете иметь несколько определений для каждого текста редактирования.
просто сравните hash-коды edittext и строки, например, используя метод hashCode ()
@Override public void afterTextChanged(Editable s) { if (editext.getText().hashCode() == s.hashCode()){ type1Total(type1List); } }
Это то, что я сделал …
private 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) { if (editText1.getText().length() > 0 && editText2.getText().length() > 0 && editText3.getText().length() > 0) { button.setEnabled(true); } else { button.setEnabled(false); } } @Override public void afterTextChanged(Editable s) { }
Затем просто добавили TextWatcher в каждый EditText в методе onCreate и также по умолчанию здесь установили setEnabled (false).
button.setEnabled(false); editText1.addTextChangedListener(textWatcher); editText2.addTextChangedListener(textWatcher); editText3.addTextChangedListener(textWatcher);