android บน Text Change Listener


265

ฉันมีสถานการณ์ที่มีสองช่อง และfield1 field2สิ่งที่ฉันต้องการทำว่างเปล่าfield2เมื่อfield1มีการเปลี่ยนแปลงและในทางกลับกัน ดังนั้นในตอนท้ายมีเพียงหนึ่งฟิลด์เท่านั้นที่มีเนื้อหาอยู่

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

มันทำงานได้ดีถ้าฉันแนบaddTextChangedListenerไปfield1เท่านั้น แต่เมื่อฉันทำมันสำหรับทั้งสองฟิลด์แอปขัดข้อง เห็นได้ชัดว่าพวกเขาพยายามที่จะเปลี่ยนแปลงซึ่งกันและกันอย่างไม่มีกำหนด เมื่อfield1การเปลี่ยนแปลงถูกลบfield2ในขณะ field2นี้การเปลี่ยนแปลงจะถูกล้างfield1และต่อไป ...

ใครช่วยแนะนำวิธีแก้ปัญหาใด ๆ ?


สำหรับผู้ใช้รายใหม่ไปหาการผูกข้อมูลแบบสองทางโดยใช้เขตข้อมูลที่สังเกตได้ซึ่งทำให้โซลูชันทั้งหมดที่มีในที่นี้อาจสร้างstarting waiting blocking gc allocข้อผิดพลาดประเภทนี้ซึ่งอาจนำไปสู่ข้อผิดพลาดและแฮงเอาท์ .. ปลอดภัยและแนะนำโดย google ตอนนี้ ..
Maifee Ul Asad

คำตอบ:


460

คุณสามารถเพิ่มการตรวจสอบเพื่อล้างเฉพาะเมื่อข้อความในฟิลด์ไม่ว่างเปล่า (เช่นเมื่อความยาวแตกต่างจาก 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

นอกจากนี้ยังโปรดเคารพการตั้งชื่ออนุสัญญา


1
วิธีตรวจจับหลังจากเปลี่ยนแปลงฟิลด์ทั้งหมดเนื่องจากตรวจจับทุกครั้งที่มีการเปลี่ยนแปลงเมื่อกดปุ่มใด ๆ
Rafael Guimarães

20

ฉันรู้ว่านี่เก่า แต่บางคนอาจเจอเรื่องนี้อีกซักวัน

ฉันมีปัญหาที่คล้ายกันซึ่งฉันจะเรียก setText บน EditText และ 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();
   }
  });

11

หากคุณใช้ Kotlin สำหรับการพัฒนา Android คุณสามารถเพิ่ม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) {}
    })

5

คำตอบช้าไปหน่อย แต่นี่เป็นคำตอบที่นำกลับมาใช้ใหม่ได้:

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

ดังนั้นเมื่อมีการใช้งานด้านบนการsetText()โทรใด ๆ ที่เกิดขึ้นภายใน TextWatcher จะไม่ส่งผลให้ 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

ฉันยังประสบปัญหาเดียวกันและรับstackOverflowข้อยกเว้นต่อไปและฉันมาพร้อมกับวิธีแก้ไขปัญหาต่อไปนี้

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;


1
"stack full" ฉันคิดว่าคุณหมายถึง Stack Overflow;)
Droid

4

คุณยังสามารถใช้วิธีการ hasFocus ():

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

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


1
สิ่งที่เกี่ยวกับ editText.setText เมื่อผู้ใช้ป้อนเข้าไป EditText มีโฟกัสในกรณีนี้
Evgenii Vorobei

ทางออกที่ดีที่สุด
Syed Hissaan

3

ตรวจสอบ String ก่อนตั้งค่าอื่นเป็นค่าEditTextว่าง หากField1ว่างเปล่าทำไมต้องเปลี่ยนอีกครั้งเป็น ("") เพื่อให้คุณสามารถตรวจสอบขนาดของสตริงของคุณด้วยs.lenght ()หรือวิธีแก้ปัญหาอื่น ๆ

อีกวิธีที่คุณสามารถตรวจสอบความยาวของสตริงได้:

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

2

ฉันเขียนส่วนขยายของตัวเองสำหรับสิ่งนี้มีประโยชน์มากสำหรับฉัน (Kotlin)

คุณสามารถเขียนได้เช่นเดียวกับที่:

editText.customAfterTextChanged { editable -> 
    //You have accessed the editable object. 
}

ส่วนขยายของฉัน:

fun EditText.customAfterTextChanged(action: (Editable?)-> Unit){
    this.addTextChangedListener(object : TextWatcher {
       override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
       override fun afterTextChanged(editable: Editable?) {
        action(editable)
    }
})}

2
editText.addTextChangedListener(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) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });

ในรหัสนี้ noteid นั้นเป็นข้อโต้แย้งที่นำกลับมาซึ่งจะถูกใส่เข้าไปในการเยื้องหรือผ่านการเยื้อง

  Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);

รหัสในข้อเสียนั้นเป็นรหัสพิเศษถ้าคุณต้องการเข้าใจให้ชัดเจนยิ่งขึ้น

how to make the menu or insert the menu in our code , 
    create the  menu folder this the folder created by going into the raw
    ->rightclick->
    directory->name the folder as you wish->
    then click on the directory formed->
    then click on new file and then name for file as you wish ie the folder name file
    and now type the 2 lines code in it and see the magic.

รหัสกิจกรรมใหม่ที่ชื่อว่าเป็น NoteEditor.java เพื่อการแก้ไขแอปของฉันเป็นแอปโน้ตที่เป็นพื้นฐาน

package com.example.elavi.notes;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.Toast;

import static android.media.CamcorderProfile.get;
public class NoteEditorActivity extends AppCompatActivity {
    EditText editText;
    int noteid;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_note_editor);
        editText = findViewById(R.id.editText);
        Intent intent = getIntent();
         noteid = intent.getIntExtra("noteid", -1);
        if (noteid != -1) {
            String text = MainActivity.notes.get(noteid);
            editText.setText(text);

           Toast.makeText(getApplicationContext(),"The arraylist content is"+MainActivity.notes.get(noteid),Toast.LENGTH_SHORT).show();
        }
        else
        {
            Toast.makeText(getApplicationContext(),"Here we go",Toast.LENGTH_SHORT).show();
            MainActivity.notes.add("");
            noteid=MainActivity.notes.size()-1;
        }
        editText.addTextChangedListener(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) {
                if (noteid != -1) {
                    MainActivity.notes.set(noteid, String.valueOf(charSequence));
                    MainActivity.arrayAdapter.notifyDataSetChanged();
                }
            }
            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }
}

1

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

เราสามารถลบ TextWatcher สำหรับเขตข้อมูลก่อนที่จะแก้ไขข้อความแล้วเพิ่มกลับหลังจากแก้ไขข้อความ

ประกาศ Text Watchers สำหรับทั้งfield1และfield2เป็นตัวแปรแยกต่างหากเพื่อให้พวกเขามีชื่อ: เช่นสำหรับfield1

private TextWatcher Field_1_Watcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

};

จากนั้นเพิ่มผู้เฝ้าดูโดยใช้ชื่อ: field1.addTextChangedListener(Field_1_Watcher)สำหรับfield1และ field2.addTextChangedListener(Field_2_Watcher)สำหรับfield2

ก่อนที่จะเปลี่ยนข้อความfield2ลบ TextWatcher: field2.removeTextChangedListener(Field_2_Watcher) เปลี่ยนข้อความ: field2.setText("")

จากนั้นเพิ่ม TextWatcher กลับมา: field2.addTextChangedListener(Field_2_Watcher)

ทำเช่นเดียวกันสำหรับฟิลด์อื่น


-3

เพิ่มพื้นหลังแบบไดนามิกในonCreateวิธีการ:

getWindow().setBackgroundDrawableResource(R.drawable.background);

ลบพื้นหลังออกจาก XML

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