Làm cách nào để sử dụng Trình xem văn bản đơn cho nhiều EditTexts?


Câu trả lời:


190

Tôi chỉ gặp phải vấn đề này. Tôi đã giải quyết nó bằng cách tạo ra một triển khai lớp bên trong, trong TextWatcherđó lấy View làm đối số. Sau đó, trong quá trình thực hiện phương thức, chỉ cần bật chế độ xem để xem cái nào Editableđến từ

Tờ khai:

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

Sử dụng:

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
Bạn có thể vui lòng cho biết 'mô hình' trong đoạn mã trên là gì và khai báo nó ở đâu không?
YuDroid

33
Câu trả lời này là không Single TextWatcher for multiple EditTexts. Đây là 3 trường hợp của một lớp TextWatcher. Vì vậy, 3 TextWatchers riêng biệt đang kiểm soát 3 EditTexts.
Bobs

2
Giải pháp được đề xuất không phải là một TextWatcher cho một số EditTexts. Kiểm tra câu trả lời này: stackoverflow.com/a/13787221/779408
Bobs

2
Hoạt động như một bùa mê, kết hợp điều này với một đoạn chứa các yếu tố hình thức để không mất dữ liệu khi thay đổi hướng định hướng.
Mathijs

1
@breceivemail Để hoàn toàn công bằng, "TextWatcher đơn" không nhất thiết có nghĩa là một trường hợp duy nhất, cũng có thể là một lớp duy nhất.
Malcolm

42

Nếu bạn muốn chỉ sử dụng afterTextChanged so sánh các chỉnh sửa:

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

10
Điều này sẽ chỉ hoạt động chính xác nếu bạn sử dụng ==thay vì .equals().
Jarett Millard

2
Bạn là thiên tài! Đây chỉ là so sánh các con trỏ không phải là giá trị thực được lưu trữ trên Editable! Đúng!
Burak Tamtürk

3
Nếu mEditText1 và mEditText2 có cùng một văn bản thì sao?
Tuss

@tuss đó là lý do tại sao chúng được so sánh bằng tham chiếu thay vì giá trị
Joakim

1
@Tomasz Cái này hoạt động thế nào? Bạn đã triển khai TextWatcher chưa? Bạn không phải ghi đè ba phương pháp nếu bạn làm?
leo núi

10

Thực hiện MultiTextWatcher

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

Sử dụng

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

Tại sao bạn lại tạo một lớp khác để xâu chuỗi chúng?! Ý tôi là bạn vẫn không biết TextViewsự thay đổi đến từ đâu.
Farid

10

Nếu bạn muốn sử dụng so sánh onTextChangedhashCode() được đề cập dưới đây -

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

}

Hoặc là

Nếu bạn muốn sử dụng afterTextChanged so sánh Editableđược đề cập dưới đây -

@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

Nó sẽ hoạt động với mã này

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

        }
    };

Sau đó thêm điều này vào oncreate

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

Vậy mOutputText từ đâu?
Kimi Chiu

5

Tôi biết đây là một vấn đề cũ, và có quyết định đúng đắn. Tôi sẽ viết riêng của họ, có thể nó sẽ giúp được ai đó.

Mô phỏng ví dụ cổ điển nơi chúng tôi có N EditText và chúng tôi muốn hiển thị nút nếu tất cả các trường được điền. Ví dụ này có ý nghĩa, đặc biệt nếu tiếp tục sử dụng trình xác nhận cho mỗi người.

Tôi đã làm một ví dụ liên quan đến vấn đề này, nhưng bạn có thể thực hiện bất kỳ bộ nào

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

    }
}

Trông nó rất đơn giản.

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

Tôi sẽ thêm một bố cục, vì vậy bạn không lãng phí thời gian

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

Yêu cầu lớp của bạn kế thừa từ Activity và triển khai TextWatcher.

Sau đó thông qua sự kỳ diệu của đa hình, bạn chỉ cần đăng ký vào các sự kiện.

Điều này sẽ không cho bạn biết TextEdit đã thay đổi gì, tuy nhiên bằng cách sử dụng kết hợp câu trả lời này và câu trả lời của Sky Kelsey , bạn có thể sắp xếp nó một cách độc đáo.

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

Sau đó:

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

2
(Cảnh báo bài đăng rên rỉ) Anh ta có thể có mã xác thực rất giống nhau cho tất cả các điều khiển và không muốn sao chép và dán mã đó 3 lần :) Tôi đã nhấn nó trước đó, tại sao họ có thể gửi điều khiển tạo ra nhấp chuột trên onClickListener trên những thứ như TextWatcher ... Cách giải quyết duy nhất tôi có thể nghĩ đến là tạo ra 3 TextWatchers gọi cùng một quy trình nhưng với một con trỏ tới các điều khiển chỉnh sửa tương ứng của chúng.
Torp

1
@Torp, @bie: Câu trả lời này có thể được quan tâm: stackoverflow.com/questions/4283062/NH Không chắc chắn nó giải quyết chính xác vấn đề được nêu ở đây, nhưng, như được hiển thị, bạn có thể có CustomTextWatcher tự động gọi một chức năng khác có trong thông qua Có thể chỉnh sửa.
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

Đây là giải pháp của tôi cho kotlin. Bạn chỉ có thể sử dụng đẳng thức tham chiếu (===) để kiểm tra cùng một đối tượng và nó hoạt động hoàn hảo.

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

Tôi biết câu hỏi này đã cũ, tuy nhiên tôi muốn chia sẻ một trong những giải pháp của mình (trong Kotlin). Giải pháp của tôi là cải thiện câu trả lời của @Shwarz Andrei, lý do của tôi là nếu bạn muốn thao túng nhiều thứ / đối tượng hơn.

Thay vì vượt qua cả hai list of EditTextsa Buttonlàm thông số, bạn chỉ vượt qua list of editText. Sau đó, trong lớp tùy chỉnh của bạn, bạn sẽ triển khai lambda như sau:

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

Sau đó, bạn sẽ thiết lập hoặc nâng nó bên trong 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 
           }
       }
   }

Vì vậy, mỗi lần, có một sự thay đổi trong một số Chỉnh sửa, lambda của bạn được gọi

        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

Đây là cách tôi đã làm nó:

Tạo một ArrayList của EditTexts, sau đó sử dụng vòng lặp for để áp dụng TextWatcher cho tất cả EditTexts, nếu bạn có một hành vi cho tất cả editTexts, sau đó chỉ cần áp dụng nó ở đó, nếu bạn có hành vi cụ thể cho một số editTexts cụ thể, thì bạn có thể sử dụng một tuyên bố để chọn và áp dụng cho các editTexts riêng lẻ.

Đây là mã của tôi:

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

}

Hi vọng điêu nay co ich


Cảm ơn câu trả lời, nhưng đây có thực sự là cách duy nhất để làm điều đó? Ý tôi là nó có vẻ phức tạp đối với một thứ phổ biến như onTextChangedtrên EditText. Thêm một onFocusChangecho nhiều widget đơn giản hơn nhiều, vì nó đã truyền đối tượng người gửi bằng lệnh gọi phương thức. Sau đó, bạn có thể kiểm tra đối tượng nào đã kích hoạt cuộc gọi và xử lý nó từ đó.
BdR
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.