Je souhaite implémenter l'interface TextWatcher
pour plusieurs champs EditText
. Actuellement, j'utilise:
text1.addTextChangedListener(this);
text2.addTextChangedListener(this);
puis écrasant les méthodes de mon activité:
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
}
Cependant, cela fonctionne bien, mais je cherche d’autres moyens pour pouvoir identifier explicitement le champ EditText
sur lequel le SoftKeyboard
est actuellement ciblé.
Solution suggérée dans La réponse de @Sebastian Roth n'est pas un exemple de TextWatcher
pour un EditTexts
. Il s'agit d'une classe et de n instances de cette classe pour n EditTexts
.
Chaque EditText a son propre Spannable. Les événements de TextWatcher
ont ce Spannable comme paramètre s
. Je vérifie leur hashCode (identifiant unique de chaque objet). myEditText1.getText () retourne ce Spannable. Donc, si myEditText1.getText().hashCode()
est égal à s.hashCode()
, cela signifie que s
appartient à myEditText1
Donc, si vous voulez avoir une instance de TextWatcher
pour une EditTexts
, vous devriez utiliser ceci:
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);
}
}
};
et
myEditText1.addTextChangedListener(generalTextWatcher);
myEditText2.addTextChangedListener(generalTextWatcher);
Je le ferais comme ça:
@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) {
}
}
en utilisant l'idée "CustomTextWatcher", je l'ai fait
1) Création d'une nouvelle interface 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) Créé et utilisé EditTextExtended au lieu de EditText (dans mon cas):
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) Alors, où vous avez besoin d'écrire ce code:
myEditTextExtended.addTextChangedListener(this) //Let implement TextWatcherExtendedListener methods
4) les utiliser:
@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
}
Eh bien, laissez-moi savoir ce que vous en pensez.
--MODIFIER--
Si vous voulez utiliser uniquement afterTextChanged, comparez les éditeurs:
@Override
public void afterTextChanged(Editable editable) {
if (editable == mEditText1.getEditableText()) {
// DO STH
} else if (editable == mEditText2.getEditableText()) {
// DO STH
}
}
J'utilise cette solution:
Ajouter une méthode qui retourne un auditeur:
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) {
}
};
}
Ajouter un auditeur à plusieurs EditText, vous pouvez également transmettre d'autres paramètres:
editText1.addTextChangedListener(getTextWatcher(editText1));
editText2.addTextChangedListener(getTextWatcher(editText2));
editText3.addTextChangedListener(getTextWatcher(editText3));
Une autre solution consiste à ajouter OnClickListener
à EditText
et à définir une variable globale comme indiqué ci-dessous.
EditText etCurrentEditor;//Global variable
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(v instanceof EditText){
etCurrentEditor=(EditText)v;
}
}
Utilisez cet etCurrentEditor comme référence au EditText actuellement édité
@Override
public void afterTextChanged(Editable editable) {
// TODO Auto-generated method stub
switch (etCurrentEditor.getId()) {
case R.id.EDITTEXTID:
break;
default:
break;
}
}
Après avoir essayé plusieurs façons d’y parvenir, j’ai trouvé le bon moyen d’utiliser EditText.isFocused()
pour distinguer les uns des autres. Par exemple:
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
}
}
}
Global Une classe pour toutes les activités.
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) {
}
}
Je l'ai implémenté comme:
edittext1.addTextChangedListener(this);
edittext2.addTextChangedListener(this);
edittext3.addTextChangedListener(this);
et:
@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) {
}
Oui, vous pouvez utiliser plusieurs instances d'une TextWatcher
personnalisée qui stocke la TextView
. (TextView
est en fait la classe qui a addTextChangedListener
.)
Semblable à la solution hashCode ci-dessus, vous pouvez simplement vérifier si getText()==s
. Au lieu de stocker tous vos contrôles ou de findViewById
à plusieurs reprises, vous pouvez simplement analyser vous-même l’arborescence du contenu à la recherche du contrôle portant le 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;
}
}
Bien sûr, vous pouvez aussi utiliser findTextView
dans beforeTextChanged
et onTextChanged
.
Vous pouvez toujours définir TextWatcher
en tant que paramètre de la méthode addTextChangedListener
. De cette façon, vous pouvez avoir plusieurs définitions pour chaque texte modifié.
Vous pouvez le faire pour obtenir l’identifiant des textes édités. Ce n'est pas testé, mais laissez-moi savoir si cela fonctionne.
//setting textWatcher for the editText
textWatcher(owner_name);
public void textWatcher(final EditText editText){
TextWatcher watcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(editText.getId()==R.id.your_id){
//Do something
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if(editText.getId()==R.id.your_id){
//Do something
}
}
@Override
public void afterTextChanged(Editable s) { }
};
editText.addTextChangedListener(watcher);
}
il suffit de comparer les codes de hachage de l'edittext et de la chaîne comme en utilisant hashCode () method
@Override
public void afterTextChanged(Editable s) {
if (editext.getText().hashCode() == s.hashCode()){
type1Total(type1List);
}
}
C'est ce que j'ai fait ...
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) {
}
Ensuite, nous venons d'ajouter TextWatcher à chaque EditText de la méthode onCreate et également de conserver le bouton setEnabled (false) par défaut ici.
button.setEnabled(false);
editText1.addTextChangedListener(textWatcher);
editText2.addTextChangedListener(textWatcher);
editText3.addTextChangedListener(textWatcher);