회원 가입 기능을 구현하면서 사용자 입력값에 대한 유효성 검사를 해야할 때가 생겼다.

 

이름과 아이디 비밀번호 등을 입력 받으면서 이름에는 숫자, 특수문자가 들어가면 안되고 아이디는 이메일 형식으로 받아야 하고 비밀번호는 영문 숫자 특수문자 3가지 조합이 들어가야 한다. 

 

이런 유효성 검사 같이 Text 실시간 처리를 할 때 유용한 클래스가 있다.

 

바로 addTextChangedListener 와 TextWatcher이다.

 

addTextChangedListener 는 EditText 위젯에 TextWatcher를 추가하는 메소드이며 사실상 TextWatcher가 이벤트를 감지하고 처리하는데 쓰이는 주인공이다.

 

적용방법은 아래와 같다.

EditText.addTextChangedListener( object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                TODO("Not yet implemented")
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                TODO("Not yet implemented")
            }

            override fun afterTextChanged(s: Editable?) {
                TODO("Not yet implemented")
            }

        })

 

TextWatcher 는 세 가지 메서드를 정의하는 인터페이스이다.

차례대로 설명하겠다.

 

beforeTextChanged 는 텍스트가 변경되기 전에 호출되어 변경 전 처리해야할 작업을 넣어주면 된다.

매개변수를 살펴보면 s는 변경 전 텍스트를 가지고 있고 start는 변경이 시작되는 인덱스 before은 변경 전에 제거되는 문자의 수, count는 변경으로 인해 추가되는 문자의 수를 감지한다.

 

이를 통해 특정 문자의 입력을 제한하거나 수정 전에 기존 텍스트를 저장할 때 유용하게 쓸 수 있다. 예를 들어 사용자가 금지된 단어를 입력했을 때 변경을 취소하고 그 전의 텍스트로 복원시키기가 가능하다.

 

onTextChanged 는 텍스트가 변경될 때 호출되어 입력 중에 특정 패턴을 검사하거나 실시간으로 입력 내용을 반영하고자 할 때 유용하다.

 

afterTextChanged는 텍스트가 변경된 후에 호출되어 변경이 완료된 후 처리해야하는 작업이 있을 때 유용하다.

 

간단하게 로그를 찍어 살펴보자.

 

 

숫자를 빠르게 1234를 입력했다. 한 글자를 입력할 때마다 3개의 메소드가 차례대로 호출된다.

주의할 점은 before은 텍스트 변경 전 시점에 호출되기에 on과 after와 다른 값을 가지고 있다는 것이다.

 

다음은 굳이 3개의 메소드를 다 오버라이드해서 사용안할 분들은 위한 팁이다.

EditText.addTextChangedListener(@SuppressLint("RestrictedApi")
        object : TextWatcherAdapter() {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                
        })

 

TextWatcherAdapter를 통해서 원하는 메소드만 오버라이드해서 사용 가능하다. 

대신 @SuppressLint("RestrictedApi") 어노테이션을 통해 오류메시지를 강제적으로 무시해주어야 한다.

@SuppressLint("RestrictedApi") 어노테이션은 Android Studio에서 Lint 경고를 무시하도록 하는 역할을 한다.

Lint는 코드에서 잠재적인 문제를 찾아내고 경고 메시지를 통해 문제점을 알려주는 녀석이다.

 

즉, 해당 코드 라인에서 발생하는 RestrictedApi 경고를 무시하라는 의미로 해당 코드에 대한 경고를 의도적으로 무시하고자 할 때 쓰는 방법이다.

 

이 방법말고 doBeforeTextChaged, doOnTextChaged, doAfterTextChaged 도 있다.

 

유효성 검사를 한 방법에 대해서 조금 남겨본다.

 

pwdEditText.addTextChangedListener(@SuppressLint("RestrictedApi")
        object : TextWatcherAdapter() {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                pwdFlag = isValidPwd()
                signUpBtn.isEnabled = (nameFlag && ageFlag && mbtiFlag && idFlag && pwdFlag && pwdCheckFlag)
            }
        })
        
        
 fun isValidPwd() : Boolean {
        val pwdEditText = findViewById<EditText>(R.id.pwdTextInputEditText)
        val pwd = pwdEditText.text.toString()
        val pwdPattern = Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@\$!%*#?&.])[A-Za-z[0-9]\$@\$!%*#?&.]{8,16}\$")
        return if (pwdEditText.text.isEmpty()) {
            pwdEditText.error = "비밀번호를 입력해주세요."
            false
        } else if (!pwd.matches(pwdPattern)){
            pwdEditText.error = "영문, 숫자, 특수문자를 모두 포함하여 주세요."
            false
        } else {
            pwdEditText.error = null
            true
        }
    }

 

정규표현식을 통해 실시간으로 입력받는 값을 처리해주고 있다. 영문 숫자 특수문자를 모두 포함하여야 에러텍스트가 null이되면서 통과하는 형식이다.

+ Recent posts