ビューレイアウトに3つのEditText
ウィジェットがあります。 3つのTextWatcher
すべてに対して単一のEditTexts
を使用する方法はありますか?
この問題が発生しました。ビューを引数として使用するTextWatcher
の内部クラス実装を作成することで解決しました。次に、メソッドの実装で、ビューをオンにしてEditable
がどのビューから来ているかを確認します
宣言:
private class GenericTextWatcher implements TextWatcher{
private View view;
private GenericTextWatcher(View view) {
this.view = view;
}
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
public void afterTextChanged(Editable editable) {
String text = editable.toString();
switch(view.getId()){
case R.id.name:
model.setName(text);
break;
case R.id.email:
model.setEmail(text);
break;
case R.id.phone:
model.setPhone(text);
break;
}
}
}
使用法:
name = (EditText) findViewById(R.id.name);
name.setText(model.getName());
name.addTextChangedListener(new GenericTextWatcher(name));
email = (EditText) findViewById(R.id.email);
email.setText(model.getEmail());
email.addTextChangedListener(new GenericTextWatcher(email));
phone = (EditText) findViewById(R.id.phone);
phone.setText(model.getPhone());
phone.addTextChangedListener(new GenericTextWatcher(phone));
AfterTextChangedのみを使用する場合は、編集可能ファイルを比較します。
@Override
public void afterTextChanged(Editable editable) {
if (editable == mEditText1.getEditableText()) {
// DO STH
} else if (editable == mEditText2.getEditableText()) {
// DO STH
}
}
このコードで動作します
TextWatcher watcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//YOUR CODE
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//YOUR CODE
}
@Override
public void afterTextChanged(Editable s) {
String outputedText = s.toString();
mOutputText.setText(outputedText);
}
};
次に、これをoncreateに追加します
mInputText.addTextChangedListener(watcher);
e2.addTextChangedListener(watcher);
e3.addTextChangedListener(watcher);
e4.addTextChangedListener(watcher);
public class MultiTextWatcher {
private TextWatcherWithInstance callback;
public MultiTextWatcher setCallback(TextWatcherWithInstance callback) {
this.callback = callback;
return this;
}
public MultiTextWatcher registerEditText(final EditText editText) {
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
callback.beforeTextChanged(editText, s, start, count, after);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
callback.onTextChanged(editText, s, start, before, count);
}
@Override
public void afterTextChanged(Editable editable) {
callback.afterTextChanged(editText, editable);
}
});
return this;
}
interface TextWatcherWithInstance {
void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after);
void onTextChanged(EditText editText, CharSequence s, int start, int before, int count);
void afterTextChanged(EditText editText, Editable editable);
}
}
new MultiTextWatcher()
.registerEditText(editText1)
.registerEditText(editText2)
.registerEditText(editText3)
.setCallback(new TextWatcherWithInstance() {
@Override
public void beforeTextChanged(EditText editText, CharSequence s, int start, int count, int after) {
// TODO: Do some thing with editText
}
@Override
public void onTextChanged(EditText editText, CharSequence s, int start, int before, int count) {
// TODO: Do some thing with editText
}
@Override
public void afterTextChanged(EditText editText, Editable editable) {
// TODO: Do some thing with editText
}
});
onTextChanged compare hashCode()
以下を使用する場合-
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if(charSequence.hashCode() == first_edit_text.getText().hashCode()){
// do other things
}
if(charSequence.hashCode() == second_edit_text.getText().hashCode()){
// do other things
}
}
または
afterTextChanged compare Editable
を使用したい場合-
@Override
public void afterTextChanged(Editable editable) {
if (editable == first_edit_text.getEditableText()) {
// do other things
} else if (editable == second_edit_text.getEditableText()) {
// do other things
}
}
これは古い問題であり、正しい決定があることは知っています。私は彼ら自身を書きます、多分それは誰かを助けるでしょう。
N EditTextがある古典的な例をエミュレートし、すべてのフィールドが埋められている場合にボタンを表示したい。この例は、特にそれぞれにバリデーターをさらに使用する場合に意味があります。
この問題に関して例を作成しましたが、任意のセットを実行できます
public class MultiEditText extends AppCompatActivity{
EditText ed_1, ed_2, ed_3;
Button btn_ok;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.multi_edit_text);
ed_1 = (EditText) findViewById(R.id.ed_1);
ed_2 = (EditText) findViewById(R.id.ed_2);
ed_3 = (EditText) findViewById(R.id.ed_3);
btn_ok = (Button) findViewById(R.id.btn_ok);
btn_ok.setEnabled(false);
//if want more here can cycle interface List
EditText[] edList = {ed_1, ed_2, ed_3}; CustomTextWatcher textWatcher = new CustomTextWatcher(edList, btn_ok); for (EditText editText : edList) editText.addTextChangedListener(textWatcher);
}
}
今はとてもシンプルに見えます
public class CustomTextWatcher implements TextWatcher {
View v;
EditText[] edList;
public CustomTextWatcher(EditText[] edList, Button v) {
this.v = v;
this.edList = edList;
}
@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) {
for (EditText editText : edList) {
if (editText.getText().toString().trim().length() <= 0) {
v.setEnabled(false);
break;
}
else v.setEnabled(true);
}
}
}
レイアウトを追加するので、時間を無駄にしません
<RelativeLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:padding="16dp">
<EditText
Android:id="@+id/ed_1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentTop="true"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="8dp" />
<EditText
Android:id="@+id/ed_2"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_below="@+id/ed_1"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="8dp" />
<EditText
Android:id="@+id/ed_3"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_below="@+id/ed_2"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="8dp" />
<Button
Android:id="@+id/btn_ok"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_below="@+id/ed_3"
Android:layout_centerHorizontal="true"
Android:layout_marginTop="8dp"
Android:text="OK" />
</RelativeLayout>
クラスにActivityを継承させ、TextWatcherを実装します。
次に、ポリモーフィズムの魔法を通して、イベントにサブスクライブするだけです。
これはTextEditが何を変更したかを教えてくれませんが、これと Sky Kelsey の組み合わせを使用すると、うまく整理できます。
public YourActivity extends Activity implements TextWatcher {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_YourActivity);
//Subscribe to the events
EditText txt1 = (EditText) findViewById(R.id.txt1);
txt1.addTextChangedListener(this);
EditText txt2 = (EditText) findViewById(R.id.txt2);
txt2.addTextChangedListener(this);
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
EditText txt1 = (EditText) findViewById(R.id.txt1);
EditText txt2 = (EditText) findViewById(R.id.txt2);
// You probably only want the text value from the EditText. But you get the idea.
doStuff(txt1,txt2);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.calc, menu);
return true;
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// TODO Auto-generated method stub
}
}
TextWatcher watcher = 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) {
}
@Override
public void afterTextChanged(Editable editable) {
}
};
次に:
editText1.addTextChangedListener(watcher);
editText2.addTextChangedListener(watcher);
editText3.addTextChangedListener(watcher);
ここに私がそれをした方法があります:
EditTextのArrayListを作成し、forループを使用して、すべてのeditTextに1つの動作がある場合、すべてのEditTextにTextWatcherを適用し、特定のeditTextに特定の動作がある場合、そこに適用します。個々のeditTextを選択して適用するステートメント...ここに私のコードがあります:
ArrayList<EditText> editTexts = new ArrayList<>(); // Container list
editText1 = (EditText) findViewById(R.id.editText1);
editText2 = (EditText) findViewById(R.id.editText2);
editText3 = (EditText) findViewById(R.id.editText3);
editTexts.add(editText1); // editTexts[0]
editTexts.add(editText2); // editTexts[1]
editTexts.add(editText3); // editTexts[2]
for (final EditText editText : editTexts) { //need to be final for custom behaviors
editText.addTextChangedListener(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) {
//Apply general behavior for all editTexts
if (editText == editTexts.get(1)) {
//Apply custom behavior just for this editText
}
}
});
}
お役に立てれば
public class MainActivity extends AppCompatActivity{
EditText value1, value2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//instantiate EditText controls
value1 = (EditText)findViewById(R.id.txtValue1);
value2 = (EditText)findViewById(R.id.txtValue2);
//set up text changed listener
value1.addTextChangedListener(new TextChange(value1));
value2.addTextChangedListener(new TextChange(value2));
//inner class
private class TextChange implements TextWatcher {
View view;
private TextChange (View v) {
view = v;
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
switch (view.getId()) {
case R.id.txtValue1:
//insert your TextChangedListener codes here
break;
case R.id.txtValue2:
//insert your TextChangedListener codes here
break;
}
}
}
}
}
私はこの質問が古いことを知っていますが、(Kotlinで)私の解決策の1つを共有したかったです。私の解決策は、@ Shwarz Andreiの答えの改善です。私の理由は、より多くのもの/オブジェクトを操作したい場合です。
list of EditTexts
とa Button
の両方をパラメーターとして渡す代わりに、list of editText
のみを渡します。次に、カスタムクラス内で、次のようなラムダを実装します。
var hasFilled:((Boolean)->Unit)? = null
次に、afterTextChanged
内で設定またはレイズします
override fun afterTextChanged(p0: Editable?) {
for (edit in _editTextList) {
if (edit?.text.toString().trim().isEmpty()) {
hasFilled?.invoke(false) //<-- here
break
} else {
hasFilled?.invoke(true) //<--- here
}
}
}
したがって、毎回、ラムダが呼び出されるEditTextに変更があります
val editTexts = listOf(emailEditText,passwordEditText) // your list of editText
val textWatcher = customTextWatcher(editTexts) // initialize your custom object
editTexts.forEach { it -> it?.addTextChangedListener(textWatcher) } // each editText would listen for changes
textWatcher.hasFilled = { value -> // now you have access to your lambda
if (value != true) {
// change the state of the button to unable
// do other things
} else {
// change the state of the button to enable
// do other things
}
}
これがkotlinに対する私のソリューションです。参照等価(===)を使用して同じオブジェクトをチェックするだけで、完全に機能します。
val mTextWatcher = object : TextWatcher {
override fun afterTextChanged(et: Editable?) {
when {
et === et1.editableText -> {
Toast.makeText(this@MainActivity, "EditText 1", Toast.LENGTH_LONG).show()
}
et === et2.editableText -> {
Toast.makeText(this@MainActivity, "EditText 2", Toast.LENGTH_LONG).show()
}
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
}
et1.addTextChangedListener(mTextWatcher)
et2.addTextChangedListener(mTextWatcher)