EditText
Customer Text Watcher 가있는 필드가 있습니다. 코드에서 내가 사용하는 EditText의 값을 변경해야합니다 .setText("whatever")
.
문제는 내가 변경하자마자 afterTextChanged
무한 루프를 생성하는 메서드가 호출됩니다. afterTextChanged를 트리거하지 않고 텍스트를 어떻게 변경할 수 있습니까?
afterTextChanged 메서드에 텍스트가 필요하므로 TextWatcher
.
답변
감시자의 등록을 취소 한 다음 다시 등록 할 수 있습니다.
또는 사용자가 텍스트를 직접 변경 한시기를 감시자가 알 수 있도록 플래그를 설정할 수 있습니다 (따라서 무시해야 함).
답변
짧은 답변
사용자 및 프로그램 트리거 이벤트를 구분하기 위해 현재 포커스가있는 뷰를 확인할 수 있습니다.
EditText myEditText = (EditText) findViewById(R.id.myEditText);
myEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (myEditText.hasFocus()) {
// is only executed if the EditText was directly changed by the user
}
}
//...
});
긴 대답
짧은 답변에 추가로 : myEditText
호출해야하는 텍스트를 프로그래밍 방식으로 변경할 때 이미 포커스가있는 경우를 호출 clearFocus()
한 다음 setText(...)
포커스를 다시 요청한 후 호출 합니다. 이를 유틸리티 함수에 넣는 것이 좋습니다.
void updateText(EditText editText, String text) {
boolean focussed = editText.hasFocus();
if (focussed) {
editText.clearFocus();
}
editText.setText(text);
if (focussed) {
editText.requestFocus();
}
}
Kotlin의 경우 :
Kotlin은 확장 기능을 지원하므로 유틸리티 기능은 다음과 같습니다.
fun EditText.updateText(text: String) {
val focussed = hasFocus()
if (focussed) {
clearFocus()
}
setText(text)
if (focussed) {
requestFocus()
}
}
답변
public class MyTextWatcher implements TextWatcher {
private EditText et;
// Pass the EditText instance to TextWatcher by constructor
public MyTextWatcher(EditText et) {
this.et = et;
}
@Override
public void afterTextChanged(Editable s) {
// Unregister self before update
et.removeTextChangedListener(this);
// The trick to update text smoothly.
s.replace(0, s.length(), "text");
// Re-register self after update
et.addTextChangedListener(this);
}
}
용법:
et_text.addTextChangedListener(new MyTextWatcher(et_text));
editable.replace () 대신 editText.setText () 를 사용하는 경우 텍스트를 빠르게 입력 할 때 약간의 지연을 느낄 수 있습니다 .
답변
수정하기 쉬운 트릭 … 새 편집 텍스트 값을 파생하는 논리가 멱등 성인 한 (아마도 그럴 것이지만 말만하면됩니다). 리스너 메소드에서 현재 값이 값을 마지막으로 수정 한 시간과 다른 경우에만 편집 텍스트를 수정하십시오.
예 :
TextWatcher tw = new TextWatcher() {
private String lastValue = "";
@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) {
// Return value of getNewValue() must only depend
// on the input and not previous state
String newValue = getNewValue(editText.getText().toString());
if (!newValue.equals(lastValue)) {
lastValue = newValue;
editText.setText(newValue);
}
}
};
답변
나는 그렇게 사용합니다.
mEditText.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) {
if (mEditText.isFocused()) { //<-- check if is focused
mEditText.setTag(true);
}
}
});
프로그래밍 방식으로 텍스트를 변경해야 할 때마다 먼저 포커스를 지 웁니다.
mEditText.clearFocus();
mEditText.setText(lastAddress.complement);
답변
Kotlin DSL 구문을 사용하여 이에 대한 일반적인 솔루션을 얻을 수 있습니다.
fun TextView.applyWithDisabledTextWatcher(textWatcher: TextWatcher, codeBlock: TextView.() -> Unit) {
this.removeTextChangedListener(textWatcher)
codeBlock()
this.addTextChangedListener(textWatcher)
}
그리고 TextWatcher 내에서 다음과 같이 사용할 수 있습니다.
editText.applyWithDisabledTextWatcher(this) {
text = formField.name
}
답변
이것은 나를 위해 잘 작동합니다.
EditText inputFileName; // = (EditText)findViewbyId(R.id...)
inputFileName.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
//unregistering for event in order to prevent infinity loop
inputFileName.removeTextChangedListener(this);
//changing input's text
String regex = "[^a-z0-9A-Z\\s_\\-]";
String fileName = s.toString();
fileName = fileName.replaceAll(regex, "");
s.replace(0, s.length(), fileName); //here is setting new text
Log.d("tag", "----> FINAL FILE NAME: " + fileName);
//registering back for text changes
inputFileName.addTextChangedListener(this);
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
public void onTextChanged(CharSequence s, int start, int before, int count) { }
});