web-dev-qa-db-ja.com

テキスト変更リスナーのアンドロイド

私は2つの分野がある状況を持っています。 field1field2field2が変更されたときに私がしたいのは空のfield1だけです。そのため、最後には1つのフィールドにしかコンテンツがありません。

field1 = (EditText)findViewById(R.id.field1);
field2 = (EditText)findViewById(R.id.field2);

field1.addTextChangedListener(new TextWatcher() {

   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) {
      field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   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) {
     field1.setText("");
   }
  });

addTextChangedListenerfield1にのみ付けてもうまく動作しますが、両方のフィールドに対してそれを行うとアプリがクラッシュします。明らかに彼らは無期限にお互いを変えようとしているからです。 field1が変更されると、現時点でfield2をクリアします。field2は変更されるのでfield1をクリアします。

誰かが何か解決策を提案できますか?

195
inrob

あなたは、フィールドのテキストが空でないとき(つまり、長さが0と異なるとき)にのみクリアするためにチェックを追加することができます。

field1.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

   @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(s.length() != 0)
        field2.setText("");
   }
  });

field2.addTextChangedListener(new TextWatcher() {

   @Override
   public void afterTextChanged(Editable s) {}

   @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(s.length() != 0)
         field1.setText("");
   }
  });

TextWatcherここ のドキュメント。

命名規則を尊重してください

365
user2336315

私はこれが古いことを知っていますが、誰かがいつかまたこれに遭遇するかもしれません。

私はEditTextでsetTextを呼び出し、それが欲しくないときにonTextChangedが呼び出されるという同様の問題を抱えていました。私の最初の解決策は、リスナーによるダメージを元に戻すためにsetText()を呼び出した後にコードを書くことでした。しかし、それはそれほどエレガントではありませんでした。いくつかの調査とテストを行った後、getText()。clear()を使用するとsetText( "")とほぼ同じ方法でテキストがクリアされることがわかりました。私の問題を解決しました。私はすべてのsetText( "")呼び出しをgetText()。clear()に切り替えましたが、もう包帯は必要ありませんでした。それであなたの問題も解決するでしょう。

これを試して:

Field1 = (EditText)findViewById(R.id.field1);
Field2 = (EditText)findViewById(R.id.field2);

Field1.addTextChangedListener(new TextWatcher() {

   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) {
      Field2.getText().clear();
   }
  });

Field2.addTextChangedListener(new TextWatcher() {

   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) {
     Field1.getText().clear();
   }
  });
13
BobVicktor

Androidの開発にKotlinを使用している場合は、次のコードを使用してTextChangedListener()を追加できます。

myTextField.addTextChangedListener(object : TextWatcher{
        override fun afterTextChanged(s: Editable?) {}

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}

        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })
6
iHulk

少し遅れた回答ですが、再利用可能な解決策があります。

/**
 * An extension of TextWatcher which stops further callbacks being called as 
 * a result of a change happening within the callbacks themselves.
 */
public abstract class EditableTextWatcher implements TextWatcher {

    private boolean editing;

    @Override
    public final void beforeTextChanged(CharSequence s, int start, 
                                                    int count, int after) {
        if (editing)
            return;

        editing = true;
        try {
            beforeTextChange(s, start, count, after);
        } finally {
            editing = false;
        }
    }

    protected abstract void beforeTextChange(CharSequence s, int start, 
                                                     int count, int after);

    @Override
    public final void onTextChanged(CharSequence s, int start, 
                                                int before, int count) {
        if (editing)
            return;

        editing = true;
        try {
            onTextChange(s, start, before, count);
        } finally {
            editing = false;
        }
    }

    protected abstract void onTextChange(CharSequence s, int start, 
                                            int before, int count);

    @Override
    public final void afterTextChanged(Editable s) {
        if (editing)
            return;

        editing = true;
        try {
            afterTextChange(s);
        } finally {
            editing = false;
        }
    }

    public boolean isEditing() {
        return editing;
    }

    protected abstract void afterTextChange(Editable s);
}

そのため、上記を使用した場合、TextWatcher内でsetText()呼び出しが発生しても、TextWatcherが再度呼び出されることはありません。

/**
 * A setText() call in any of the callbacks below will not result in TextWatcher being 
 * called again.
 */
public class MyTextWatcher extends EditableTextWatcher {

    @Override
    protected void beforeTextChange(CharSequence s, int start, int count, int after) {
    }

    @Override
    protected void onTextChange(CharSequence s, int start, int before, int count) {
    }

    @Override
    protected void afterTextChange(Editable s) {
    }
}
5
Eurig Jones

私はまた同じ問題に直面し、スタックフル例外を取得し続けており、私は以下の解決策を考え出しています。

    edt_amnt_sent.addTextChangedListener(new TextWatcher() {    
        @Override
        public void afterTextChanged(Editable s) {

            if (skipOnChange)
                return;

            skipOnChange = true;
            try {
                //method
                }
            } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                skipOnChange = false;
            }
        }
    });

    edt_amnt_receive.addTextChangedListener(new TextWatcher() {


        @Override
        public void afterTextChanged(Editable s) {

            if (skipOnChange)
                return;

            skipOnChange = true;
            try 
            {
                //method
            } catch (NumberFormatException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                skipOnChange = false;
            }
        }
    });

最初に宣言されたブール値skipOnChange = false;

4
Sumit

別のEditTextを空に設定する前に、Stringを確認してください。 Field1が空の場合、なぜ再度( "")に変更する必要がありますか?だからあなたは s.lenght()であなたの文字列のサイズをチェックすることができます または他の解決策

あなたは文字列の長さをチェックすることができるもう一つの方法は次のとおりです。

String sUsername = Field1.getText().toString();
if (!sUsername.matches(""))
{
// do your job
}
3

HasFocus()メソッドを使うこともできます。

public void onTextChanged(CharSequence s, int start,
     int before, int count) {
     if (Field2.hasfocus()){
         Field1.setText("");
     }
   }

ユーザーが入力したとおりに温度スケールを変換するために取り組んでいた大学の課題についてこれをテストしました。

3
renam