วิธีใช้คลาส TextWatcher ใน Android


103

ใครช่วยบอกวิธีมาสก์สตริงย่อยในEditTextหรือวิธีเปลี่ยนEditText อินพุตสตริงย่อยเป็นประเภทรหัสผ่านหรือแทนที่ด้วยอักขระอื่นเช่น 123xxxxxxxxx3455 นี้

 String contents = et1.getText().toString();
 et1.setText(contents.replace.substring(0, contents.length()-2),"*");

โปรดบอกฉันว่าฉันจะใช้TextWatcherวิธีนี้ใน Android ได้อย่างไร

คำตอบ:


174

สำหรับการใช้งานTextWatcher...

et1.addTextChangedListener(new TextWatcher() {
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

        // TODO Auto-generated method stub
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        // TODO Auto-generated method stub
    }

    @Override
    public void afterTextChanged(Editable s) {

        // TODO Auto-generated method stub
    }
});

59
จะทำอย่างไรกับ TextWatcher นี้ ให้รายละเอียดเพิ่มเติมเพื่อความเข้าใจที่ดีขึ้น
Paresh Mayani

ในวิธีการที่ถูกแทนที่สำหรับผู้เฝ้าดูข้อความ คุณสามารถมาสก์ข้อความที่คุณต้องการจริงๆ
Dinesh Prajapati

2
แต่ฉันไม่รู้วิธีใช้ TextWatcher คุณสามารถอธิบายด้วยตัวอย่างเล็ก ๆ น้อย ๆ ขอบคุณสำหรับแนวทางของคุณ
นักพัฒนา Android

ใส่รหัสนี้ใน java .. ทันทีที่ผู้ใช้พิมพ์ข้อความจะเรียกวิธีการใดวิธีหนึ่ง ... ตามชื่อของฟังก์ชัน
Dinesh Prajapati

1
ที่จริงแล้วถ้านี่เป็นข้อกำหนดก็ไม่ควรใช้โปรแกรมเฝ้าดูข้อความมันจะวนรอบไม่สิ้นสุด
Dinesh Prajapati

119

TextWatcherอินเตอร์เฟซที่มี 3 วิธีการเรียกกลับซึ่งเรียกว่าทั้งหมดในลำดับต่อไปนี้เมื่อมีการเปลี่ยนแปลงเกิดขึ้นกับข้อความ:

beforeTextChanged(CharSequence s, int start, int count, int after)

เรียกก่อนที่การเปลี่ยนแปลงจะถูกนำไปใช้กับข้อความ พารามิเตอร์ข้อความก่อนการเปลี่ยนแปลงใด ๆ ที่นำมาใช้ พารามิเตอร์เป็นตำแหน่งของจุดเริ่มต้นของการเปลี่ยนแปลงส่วนหนึ่งในข้อความ พารามิเตอร์เป็นความยาวของส่วนที่มีการเปลี่ยนแปลงในลำดับตั้งแต่ตำแหน่ง และพารามิเตอร์เป็นความยาวของลำดับใหม่ที่จะเข้ามาแทนที่ส่วนหนึ่งของลำดับจากการ คุณต้องไม่เปลี่ยนข้อความในจากวิธีนี้ (โดยใช้)
s
start
countsstart
aftersstartstart+count
TextViewmyTextView.setText(String newText)

onTextChanged(CharSequence s, int start, int before, int count)

คล้ายกับbeforeTextChangedวิธีการ แต่เรียกว่าหลังจากข้อความเปลี่ยนไป พารามิเตอร์ข้อความหลังจากที่เปลี่ยนแปลงได้ถูกนำมาใช้ พารามิเตอร์เป็นเช่นเดียวกับในวิธีการ พารามิเตอร์เป็นพารามิเตอร์ในวิธีการ beforeTextChanged และพารามิเตอร์คือพารามิเตอร์ในเมธอด beforeTextChanged คุณต้องไม่เปลี่ยนข้อความในจากวิธีนี้ (โดยใช้)
s
startbeforeTextChanged
countafter
beforecount
TextViewmyTextView.setText(String newText)

afterTextChanged(Editable s)

คุณสามารถเปลี่ยนข้อความในTextViewจากวิธีนี้
! / \ คำเตือน:เมื่อคุณเปลี่ยนข้อความในTextViewที่TextWatcherจะถูกเรียกอีกครั้งเริ่มต้นวง จำกัด จากนั้นคุณควรเพิ่มเช่นboolean _ignoreคุณสมบัติที่ป้องกันการวนซ้ำที่ไม่มีที่สิ้นสุด
ตัวอย่าง:

new TextWatcher() {
        boolean _ignore = false; // indicates if the change was made by the TextWatcher itself.

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

            _ignore = true; // prevent infinite loop
            // Change your text here.
            // myTextView.setText(myNewText);
            _ignore = false; // release, so the TextWatcher start to listen again.
        }

        // Other methods...
    }

สรุป:

ใส่คำอธิบายภาพที่นี่


คลาสที่พร้อมใช้งาน: TextViewListener

โดยส่วนตัวแล้วฉันสร้างโปรแกรมฟังข้อความที่กำหนดเองซึ่งให้ 4 ส่วนในสตริงแยกกันซึ่งสำหรับฉันแล้วใช้งานง่ายกว่ามาก

 /**
   * Text view listener which splits the update text event in four parts:
   * <ul>
   *     <li>The text placed <b>before</b> the updated part.</li>
   *     <li>The <b>old</b> text in the updated part.</li>
   *     <li>The <b>new</b> text in the updated part.</li>
   *     <li>The text placed <b>after</b> the updated part.</li>
   * </ul>
   * Created by Jeremy B.
   */

  public abstract class TextViewListener implements TextWatcher {
    /**
     * Unchanged sequence which is placed before the updated sequence.
     */
    private String _before;

    /**
     * Updated sequence before the update.
     */
    private String _old;

    /**
     * Updated sequence after the update.
     */
    private String _new;

    /**
     * Unchanged sequence which is placed after the updated sequence.
     */
    private String _after;

    /**
     * Indicates when changes are made from within the listener, should be omitted.
     */
    private boolean _ignore = false;

    @Override
    public void beforeTextChanged(CharSequence sequence, int start, int count, int after) {
        _before = sequence.subSequence(0,start).toString();
        _old = sequence.subSequence(start, start+count).toString();
        _after = sequence.subSequence(start+count, sequence.length()).toString();
    }

    @Override
    public void onTextChanged(CharSequence sequence, int start, int before, int count) {
        _new = sequence.subSequence(start, start+count).toString();
    }

    @Override
    public void afterTextChanged(Editable sequence) {
        if (_ignore)
            return;

        onTextChanged(_before, _old, _new, _after);
    }

    /**
     * Triggered method when the text in the text view has changed.
     * <br/>
     * You can apply changes to the text view from this method
     * with the condition to call {@link #startUpdates()} before any update,
     * and to call {@link #endUpdates()} after them.
     *
     * @param before Unchanged part of the text placed before the updated part.
     * @param old Old updated part of the text.
     * @param aNew New updated part of the text?
     * @param after Unchanged part of the text placed after the updated part.
     */
    protected abstract void onTextChanged(String before, String old, String aNew, String after);

    /**
     * Call this method when you start to update the text view, so it stops listening to it and then prevent an infinite loop.
     * @see #endUpdates()
     */
    protected void startUpdates(){
        _ignore = true;
    }

    /**
     * Call this method when you finished to update the text view in order to restart to listen to it.
     * @see #startUpdates()
     */
    protected void endUpdates(){
        _ignore = false;
    }
  }

ตัวอย่าง:

myEditText.addTextChangedListener(new TextViewListener() {
        @Override
        protected void onTextChanged(String before, String old, String aNew, String after) {
           // intuitive usation of parametters
           String completeOldText = before + old + after;
           String completeNewText = before + aNew + after;

           // update TextView
            startUpdates(); // to prevent infinite loop.
            myEditText.setText(myNewText);
            endUpdates();
        }
}

ปัญหาเกี่ยวกับรหัสนี้คือเคอร์เซอร์ไม่อยู่เพราะมันควรจะเป็นหรืออย่างน้อยที่สุดก็เป็นประสบการณ์ของฉัน
jonasxd360

textview เรียกวิธีการเหล่านี้หรือไม่

ฉันคิดว่าอย่างนั้น
ยายโปร

แก้ไขปัญหาเกี่ยวกับเคอร์เซอร์ด้วยวิธีนี้: โมฆะป้องกัน onTextChanged (String before, String old, String aNew, String after, Editable ลำดับได้)
Eugene Strelnikov

49

คำตอบเพิ่มเติม

นี่คือภาพเสริมสำหรับคำตอบอื่น ๆ คำตอบของฉันกับฟูลเลอร์รหัสและคำอธิบายที่เป็นที่นี่

  • สีแดง: ข้อความกำลังจะถูกลบ (แทนที่)
  • สีเขียว: ข้อความที่เพิ่งเพิ่ม (แทนที่ข้อความสีแดงเดิม)

ใส่คำอธิบายภาพที่นี่


6

ใช้ TextWatcher ใน Android

นี่คือตัวอย่างโค้ด ลองใช้addTextChangedListenerวิธีการของ TextView

addTextChangedListener(new TextWatcher() {

        BigDecimal previousValue;
        BigDecimal currentValue;

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int
                count) {
            if (isFirstTimeChange) {
                return;
            }
            if (s.toString().length() > 0) {
                try {
                    currentValue = new BigDecimal(s.toString().replace(".", "").replace(',', '.'));
                } catch (Exception e) {
                    currentValue = new BigDecimal(0);
                }
            }
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            if (isFirstTimeChange) {
                return;
            }
            if (s.toString().length() > 0) {
                try {
                    previousValue = new BigDecimal(s.toString().replace(".", "").replace(',', '.'));
                } catch (Exception e) {
                    previousValue = new BigDecimal(0);
                }
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
            if (isFirstTimeChange) {
                isFirstTimeChange = false;
                return;
            }
            if (currentValue != null && previousValue != null) {
                if ((currentValue.compareTo(previousValue) > 0)) {
                    //setBackgroundResource(R.color.devises_overview_color_green);
                    setBackgroundColor(flashOnColor);
                } else if ((currentValue.compareTo(previousValue) < 0)) {
                    //setBackgroundResource(R.color.devises_overview_color_red);

                    setBackgroundColor(flashOffColor);
                } else {
                    //setBackgroundColor(textColor);
                }
                handler.removeCallbacks(runnable);
                handler.postDelayed(runnable, 1000);
            }
        }
    });

5

มุมมองที่กว้างขึ้นเล็กน้อยของการแก้ปัญหา:

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.yourlayout, container, false);
        View tv = v.findViewById(R.id.et1);
        ((TextView) tv).addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                 SpannableString contentText = new SpannableString(((TextView) tv).getText());
                 String contents = Html.toHtml(contentText).toString();
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                // TODO Auto-generated method stub
            }

            @Override
            public void afterTextChanged(Editable s) {

                // TODO Auto-generated method stub
            }
        });
        return v;
    }

สิ่งนี้ได้ผลสำหรับฉันทำครั้งแรก


5

สร้างคลาสย่อย TextWatcher ที่กำหนดเอง:

public class CustomWatcher implements TextWatcher {

    private boolean mWasEdited = false;

    @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) {

        if (mWasEdited){

            mWasEdited = false;
            return;
        }

        // get entered value (if required)
        String enteredValue  = s.toString();

        String newValue = "new value";

        // don't get trap into infinite loop
        mWasEdited = true;
        // just replace entered value with whatever you want
        s.replace(0, s.length(), newValue);

    }
}

ตั้งค่าผู้ฟังสำหรับ EditText ของคุณ:

mTargetEditText.addTextChangedListener(new CustomWatcher());

นี่เป็นวิธีแก้ปัญหาที่ชาญฉลาดและมีน้ำหนักเบาจริงๆ! ขอบคุณ!
FRR

2

สำหรับKotlinใช้ฟังก์ชันส่วนขยาย KTX : (ใช้TextWatcherเป็นคำตอบก่อนหน้านี้)

yourEditText.doOnTextChanged { text, start, count, after -> 
        // action which will be invoked when the text is changing
    }


นำเข้าcore-KTX:

implementation "androidx.core:core-ktx:1.2.0"

1
    public class Test extends AppCompatActivity {

    EditText firstEditText;
    EditText secondEditText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        firstEditText = (EditText)findViewById(R.id.firstEditText);
        secondEditText = (EditText)findViewById(R.id.secondEditText);

        firstEditText.addTextChangedListener(new EditTextListener());

    }

    private class EditTextListener implements 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) {
            secondEditText.setText(firstEditText.getText());
        }

        @Override
        public void afterTextChanged(Editable s) {
        }
    }
}

1

หากคุณใช้กับข้อความแก้ไขข้อความ ใช้ดังนี้:. มันเหมือนกันกับการใช้กับข้อความแก้ไขอื่น ๆ

dialog.getInputEditText().addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int before, int count) {
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
        if (start<2){
                dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
            }else{
                double size =  Double.parseDouble(charSequence.toString());
                if (size > 0.000001 && size < 0.999999){
                    dialog.getActionButton(DialogAction.POSITIVE).setEnabled(true);
                }else{
                    ToastHelper.show(HistoryActivity.this, "Size must between 0.1 - 0.9");
                    dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
                }

            }
    }

    @Override
    public void afterTextChanged(Editable editable) {

    }
});

-2
editext1.addTextChangedListener(new TextWatcher() {

   @Override
    public void onTextChanged(CharSequence s, int start, int before,
    int count) {
     editext2.setText(new String(s.toString()));

          }

   @Override
     public void beforeTextChanged(CharSequence s, int start, int count,
      int after) {

         editext2.setText(new String(s.toString()));
        }

      @Override
          public void afterTextChanged(Editable s) {

          editext2.setText(new String(s.toString()));
      }

         });

สำหรับข้อมูลอ้างอิงเพิ่มเติมคลิกที่นี่http://androiddhina.blogspot.in/2015/05/android-textwatcher.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.