텍스트 변경 리스너의 안드로이드


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

내가 첨부 할 경우 잘 작동 addTextChangedListenerfield1만,하지만 난 두 필드을 위해 그것을 할 때 응용 프로그램이 충돌합니다. 분명히 그들은 서로를 무한정으로 바꾸려고하기 때문입니다. 일단 field1변경 되면 field2이 순간에 지워 field2지므로 변경 field1됩니다.

누군가 해결책을 제안 할 수 있습니까?


새로운 사용자에게는 관찰 가능한 문자열 필드를 사용하여 양방향 데이터 바인딩을 수행하십시오. 여기에 제공된 모든 솔루션으로 인해 starting waiting blocking gc alloc이러한 유형의 오류가 발생할 수 있으며, 이는 충돌 및 중단으로 이어질 수 있습니다. 따라서 데이터 바인딩으로 이동하십시오. 안전하고 지금 구글에 의해 추천 ..
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 1

20

나는 이것이 오래되었다는 것을 알고 있지만 언젠가 누군가가 이것을 다시 만날 수 있습니다.

EditText에서 setText를 호출하는 것과 비슷한 문제가 있었고 원하지 않는 경우 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

Android 개발에 Kotlin을 사용하는 경우 다음 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;
        }
    }
});

처음에 선언 boolean skipOnChange = false;


1
"스택 전체가"나는 생각하면 평균 스택 오버플로)
드로 이드

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

다른 EditText것을 비우기 전에 문자열을 확인하십시오 . 경우는 Field1필요 ( "")로 다시 변경하는 이유를 다음 비어? s.lenght () 또는 다른 솔루션으로 문자열 크기를 확인할 수 있습니다.

String의 길이를 확인할 수있는 또 다른 방법은 다음과 같습니다.

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

2

나는 이것을 위해 내 자신의 확장을 썼다. (코 틀린)

당신은 그렇게 쓸 수 있습니다 :

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를 제거한 다음 텍스트를 편집 한 후 다시 추가 할 수 있습니다.

field1field2에 대한 텍스트 감시자를 별도의 변수로 선언 하여 이름을 지정하십시오. 예 : 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)하기위한 필드 1field2.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.