Birden çok EditTexts için Single TextWatcher nasıl kullanılır?


Yanıtlar:


190

Bu problemle henüz karşılaştım. TextWatcherArgüman olarak View alan bir iç sınıf uygulaması oluşturarak çözdüm. Ardından, yöntem uygulamasında, hangisinin Editablegeldiğini görmek için görünümü açmanız yeterlidir.

Beyan:

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;
        }
    }
}

Kullanımı:

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));

1
Yukarıdaki kodda 'model' nedir ve onu nerede açıklayacağınızı söyler misiniz?
YuDroid

33
bu cevap değil Single TextWatcher for multiple EditTexts. Bir TextWatcher sınıfının 3 örneğidir. Yani 3 ayrı TextWatcher 3 EditTexts'i kontrol ediyor.
Bob'lar

2
Önerilen çözüm, bazı EditTexts için bir TextWatcher değildir. Bu yanıtı kontrol edin: stackoverflow.com/a/13787221/779408
Bobs

2
En boy yönünü değiştirirken verileri kaybetmemek için bunu form öğeleri içeren bir parça ile birleştiren bir cazibe gibi çalışır.
Mathijs Segers

1
@breceivemail Tamamen adil olmak gerekirse, "tek TextWatcher" mutlaka tek bir örnek anlamına gelmez, tek bir sınıf da olabilir.
Malcolm

42

Yalnızca afterTextChanged karşılaştırma düzenlenebilirlerini kullanmak istiyorsanız:

@Override
public void afterTextChanged(Editable editable) {
    if (editable == mEditText1.getEditableText()) {
        // DO STH
    } else if (editable == mEditText2.getEditableText()) {
        // DO STH
    }
}

10
Bu yalnızca ==yerine kullanırsanız doğru şekilde çalışacaktır .equals().
Jarett Millard

2
Sen dahisin! Bu sadece, Düzenlenebilir'de depolanan gerçek değerleri olmayan işaretçileri karşılaştırmaktır! Evet!
Burak Tamtürk

3
ya mEditText1 ve mEditText2 aynı metne sahipse?
Tuss

@tuss bu yüzden değer yerine referansa göre karşılaştırılıyorlar
Joakim

1
@Tomasz Bu nasıl çalışır? TextWatcher'ı uyguladınız mı? Eğer yaparsan üç yöntemi geçersiz kılman gerekmez mi?
leonheess

10

MultiTextWatcher Uygulaması

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);
    }
}

kullanım

    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
                }
            });

Neden onları zincirlemek için başka bir sınıf oluşturuyorsunuz ?! Demek istediğim, hala TextViewdeğişikliğin nereden geldiğini bilmiyorsun .
Farid

10

Aşağıda belirtilen onTextChanged karşılaştırmasını kullanmak istiyorsanız 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 
    }

}

Veya

Aşağıda belirtilen afterTextChanged karşılaştırmasını kullanmak istiyorsanız 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 
    }
}

9

Bu kodla çalışacak

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);

        }
    };

Sonra bunu oncreate'e ekleyin

  mInputText.addTextChangedListener(watcher);
        e2.addTextChangedListener(watcher);
        e3.addTextChangedListener(watcher);
        e4.addTextChangedListener(watcher);

Peki mOutputText nereden geliyor?
Kimi Chiu

5

Bunun eski bir sorun olduğunu biliyorum ve doğru karar var. Ben kendim yazacağım, belki birine yardımcı olur.

N EditText'in olduğu klasik örneği taklit ederek ve tüm alanlar doldurulmuşsa düğmeyi göstermek istiyoruz. Bu örnek, özellikle her biri için daha fazla doğrulayıcı kullanırsa mantıklıdır.

Konu ile ilgili bir örnek verdim ama istediğiniz seti yapabilirsiniz

MultiEditText.class

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);

    }
}

Şimdi çok basit görünüyor

CustomTextWatcher.class

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);
    }
  }
}

Bir düzen ekleyeceğim, böylece zaman kaybetmezsin

multi_edit_text.xml

<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>

5

Sınıfınızın Activity'den miras almasını ve TextWatcher'ı uygulamasını sağlayın.

Sonra polimorfizmin büyüsü sayesinde, sadece olaylara abone olmanız gerekir.

Bu size TextEdit'in neyi değiştirdiğini söylemez, ancak bunun ve Sky Kelsey'nin cevabının bir kombinasyonunu kullanarak bunu güzelce çözebilirsiniz.

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
    }
}

3
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) {
    }
};

Sonra:

editText1.addTextChangedListener(watcher);
editText2.addTextChangedListener(watcher);
editText3.addTextChangedListener(watcher);

2
(Mızmızlanma post uyarısı) Muhtemelen tüm kontroller için çok benzer doğrulama koduna sahip ve 3 kez kopyalayıp yapıştırmak istemiyor :) Daha önce ona bastım, neden onClickListener'a tıklamayı oluşturan kontrolü gönderiyorlar da göndermiyorlar TextWatcher gibi şeyler hakkında ... Aklıma gelen tek çözüm, aynı prosedürü çağıran ancak kendi düzenleme kontrollerine bir işaretçi olan 3 TextWatcher yapmaktır.
Torp

1
@Torp, @bie: Bu cevap ilgi çekici olabilir: stackoverflow.com/questions/4283062/… Burada belirtilen sorunu tam olarak çözdüğünden emin değilim, ancak gösterildiği gibi, CustomTextWatcher'ın otomatik olarak başka bir işlevi çağırmasını sağlayabilirsiniz. Düzenlenebilir geçti.
Kevin Coppock

3
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;
                 }
             }   
         }
     }
}

3

Bu benim kotlin için çözümüm. Aynı nesneyi kontrol etmek için Referans eşitliğini (===) kullanabilirsiniz ve mükemmel çalışıyor.

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)

0

Bu sorunun eski olduğunu biliyorum, ancak çözümümden birini (Kotlin'de) paylaşmak istedim. Benim çözümüm @Shwarz Andrei'nin cevabının bir iyileştirmesi, benim sebebim daha fazla şeyi / nesneyi manipüle etmek isteseydin.

Her ikisini de list of EditTextsve a Buttonparams olarak geçmek yerine, yalnızca list of editText. Sonra kendi özel sınıfınızda böyle bir lambda uygularsınız:

var hasFilled:((Boolean)->Unit)? = null 

Sonra onu içinde ayarlayacak veya yükselteceksiniz. 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 
           }
       }
   }

Yani her seferinde, bazı EditText'lerde bir değişiklik olur, lambdanız çağrılır.

        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 
            }
        }

0

İşte böyle yaptım:

Bir EditTexts ArrayList'i oluşturun ve ardından tüm EditTexts için TextWatcher'ı uygulamak için bir for döngüsü kullanın, tüm editTexts için bir davranışınız varsa, o zaman sadece oraya uygulayın, bazı özel editTexts için belirli davranışlarınız varsa, o zaman bir if kullanabilirsiniz bireysel editTexts'i seçmek ve uygulamak için ifade.

İşte kodum:

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                           
            }
        }
    });

}

Bu yardımcı olur umarım


Cevap için teşekkürler, ama gerçekten bunu yapmanın tek yolu bu mu? Demek istediğim onTextChanged, bir EditText'te olduğu kadar yaygın bir şey için biraz karmaşık görünüyor . onFocusChangeYöntem çağrısıyla gönderen nesnesini geçtiği için birden çok pencere öğesi için bir eklemek çok daha basittir. Ardından hangi nesnenin çağrıyı tetiklediğini inceleyebilir ve oradan halledebilirsiniz.
BdR
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.