Android/TextWatcher

[Android] TextWatcher로 텍스트 변경될 때마다 이벤트 처리하기

O_Gyong 2022. 11. 23.

앱에서 텍스트를 입력 중에 무언가 잘못되었다고('잘못된 입력 형식' 문구 또는 에러 ui 표시) 사용자에게 알려주는 것을 본 적이 있을 것이다.

안드로이드에서 TextWatcher라는 인터페이스를 제공하는데 TextWatcher에 정의된 메서드들을 사용하여 앞에서 말한 기능들을 구현할 수 있다.

참고 자료


TextWatcer의 메서드

TextWatcher에는 beforeTextChanged, onTextChanged, afterTextChanged가 있다.

onTextChanged는 변경된 문자열을 보여주는데 afterTextChanged가 세분화 된 것으로 보인다.

그래서 beforeTextChanged와 onTextChanged를 비교해보려 한다.

 

mBinding.etCompare.addTextChangedListener(object: TextWatcher {
    /**
     * 텍스트 변경 전
     * s:기존 문자열, start:커서 시작 위치, before:변경 전 문자 수, after:변경 후 문자 수
     */
    override fun beforeTextChanged(s: CharSequence?, start: Int, before: Int, after: Int) {
        mBinding.tvCompareBefore.text = s
        mBinding.tvCompareBeforeStart.text = start.toString()
        mBinding.tvCompareBeforeBefore.text = before.toString()
        mBinding.tvCompareBeforeAfter.text = after.toString()
    }

    /**
     * 텍스트 변경 시
     * s:변경된 문자열, start:커서 시작 위치, before:변경 전 문자 수, after:변경 후 문자 수
     */
    override fun onTextChanged(s: CharSequence?, start: Int, before: Int, after: Int) {
        mBinding.tvCompareAfter.text = s
        mBinding.tvCompareAfterStart.text = start.toString()
        mBinding.tvCompareAfterBefore.text = before.toString()
        mBinding.tvCompareAfterAfter.text = after.toString()
    }

    /**
     * 텍스트 변경 후
     * s:변경된 문자열
     */
    override fun afterTextChanged(p0: Editable?) {
        println("-")
    }
})

EditText에서 addTextChangedListener를 사용해서 TextWatcher object를 넘겨서 TextWatcher의 메서드들을 override 해줘야 한다.

 

(왼쪽)숫자만 입력, (가운데)한글(영문)만 입력, (오른쪽)특수문자만 입력

beforeTextChanged와 바뀌기 직전의 문자열을 보여주고, onTextChanged는 변경된 문자열을 보여준다.

하지만 파라미터로 받은 값(커서 시작 위치, 변경 전/후 문자 수)은 둘 다 동일하다.

 

숫자와 특수문자만 작성한 경우는 한글만 입력했을 때와 달리 문자 수에 영향을 주지 않는 것 같다.

(변경 전/후의 문자 수가 변하지 않음)

 

그리고 띄어쓰기를 할 경우에는 변경 전 문자 수는 0, 변경 후 문자 수는 1로 바뀐다.

(새로운 문자열로 판단?)

(왼쪽)잘라내기+붙여 넣기, (가운데)숫자+특수문자, (오른쪽)한글(영문)+숫자+특수문자

잘라내기와 붙여 넣기를 할 경우 그 문자 수만큼 변하는 것을 확인할 수 있다.

 

특수문자를 쓰고 숫자를 쓸 경우에는 문자 수가 변경되다가 4번째부터 초기화된다.

숫자를 쓰고 특수문자를 쓸 때는 문자 수에 반응이 없었다.

 

문자를 쓰고 숫자를 쓸 경우에는 문자 수가 계속 적용된다.(문자로 인식?)

이후에 특수문자를 하나만 붙여도 띄어쓰기를 쓴 것처럼 초기화된다.


TextWatcher로 번호 인증하기

예제로 EditText에 숫자를 입력했을 때 비밀번호와 일치하면 성공 화면, 틀리면 실패 화면을 보여주려고 한다.

val passwordNum = "487259"

mBinding.etMain.addTextChangedListener {
    if(mBinding.etMain.length() == 6) {
        mBinding.tvMain.visibility = View.VISIBLE
        if(mBinding.etMain.text.toString() == passwordNum){
            mBinding.tvMain.text = getString(R.string.auth_num_success)
            mBinding.tvMain.setTextColor(Color.GREEN)
            mBinding.vMain.setBackgroundColor(Color.BLACK)
        }else {
            mBinding.tvMain.text = getString(R.string.auth_num_fail)
            mBinding.tvMain.setTextColor(Color.RED)
            mBinding.vMain.setBackgroundColor(Color.RED)
        }
    }else {
        mBinding.tvMain.visibility = View.GONE
        mBinding.vMain.setBackgroundColor(Color.BLACK)
    }
}

TextWatcher object를 넘기지 않고 addTextChangedListener만 사용하여 텍스트가 변했는지만 확인할 수 있다.

 

문자열의 최대 길이를 6으로 설정하고 6자리가 되었을 때 비밀번호와 일치하는지 확인한다.

일치 여부에 따라 UI를 수정하고 6자리가 아닐 경우에 초기 값으로 돌려준다.

전체 코드

 


12.22 내용 수정.

댓글