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

두 개의 필드가있는 상황이 있습니다. 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됩니다.

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



답변

필드의 텍스트가 비어 있지 않은 경우 (예 : 길이가 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 여기에 대한 설명서 .

또한 명명 규칙을 준수하십시오 .


답변

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

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


답변

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


답변

대답이 약간 늦었지만 재사용 가능한 솔루션은 다음과 같습니다.

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


답변

나는 또한 같은 문제에 직면하고 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;


답변

hasFocus () 메소드를 사용할 수도 있습니다.

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

사용자가 온도를 입력 할 때 온도 스케일을 변환하기 위해 노력하고있는 대학 과제에 대해 이것을 테스트했습니다. 완벽하게 작동했으며 훨씬 간단합니다.


답변

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

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

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