[java] Text Watcher를 트리거하지 않고 EditText 텍스트를 어떻게 변경할 수 있습니까?

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