[Android] EditText에 InputFilter 적용이 안될 때

EditText를 이용할 때 입력 문자에 제한을 두어야 할 때가 있습니다.

한글만 입력이 가능하게 한거나, 특수문자 입력을 막거나 할 때 등등

보통 InputFilter를 사용하여 입력을 막도록 하는데요

최근에 개발하다가 Filter 조건을 잘 걸었지만 이상하게 동작하는 현상이 발견돼서 

기록해보려고 합니다!!!


1. InputFilter

EditText에서 InputFilter를 사용하여 특정 문자 입력을 제한, 문자열 길이 제한 조건 설정을 할 수 있습니다. 

fun EditText.filterDigitAndSpecialChar() {
    this.filters = arrayOf( InputFilter { source, start, end, dest, dstart, dend ->
        val pattern = "^[a-zA-Zㄱ-ㅣ가-힣]"
        for (index in start until end) {
            val type = source[index]
            if(!type.toString().matches(Regex(pattern))) {
                return@InputFilter ""
            }
        }
        return@InputFilter null
    })
}

InputFilter는 위 코드와 같이 사용할 수 있습니다. 저는 한글과 영문 외에 숫자와 특수문자 입력을 제한했어야 했기 때문에 정규식을 만들어 해당 Filter에 적용해주었습니다.

 

 

2. 적용되지 않는 InputFilter

 

하지만, 실행 결과를 보면.. 한글을 입력한 후 숫자를 입력했더니 입력되어 있던 문자까지 모두 사라지는 현상이 발생합니다. 공백입력이나 특수문자 입력을 제한했을 때는 정상적으로 동작하나 숫자를 입력했을 때 위 영상처럼 이상하게 동작하는 걸 발견할 수 있습니다.

 

문제를 해결하기 위해 InputFilter의 파라미터인 source, start, end 등을 로그로 확인해 보았고 특수문자 입력만 제한했을 때와 숫자까지 입력을 제한했을 때 source로 들어오는 값이 다르다는 것을 발견할 수 있었습니다.

 

//문자가 사라질 때
filterSpaceAndChar:: source: ㅇ
filterSpaceAndChar:: source: 아
filterSpaceAndChar:: source: 아8

//정상적으로 동작할 때
filterSpaceAndChar:: source: d
filterSpaceAndChar:: source: k
filterSpaceAndChar:: source: @

즉 source 로그를 찍어보면 정상적으로 동작할 때는 source에 값이 마지막에 입력된 값으로 들어오는 것을 확인할 수 있지만, 위 영상처럼 문자가 사라질 때를 확인해 보니 source에 문자와 제한 둔 숫자가 합쳐져서 들어오는 것을 확인할 수 있었습니다.

 

3. 해결 방안

source에 값이 다르게 들어오는 이유를 찾기 위해 검색하고 수정해 본 결과 xml에서 inputType에 따라 source에 넣어지는 값이 다르다는 것을 알 수 있었습니다. 설정된 inputType은 default값인 text였고 아래 참고 블로그를 통해

android:inputType="textVisiblePassword"

로 타입을 변경하니 정상동작하는 것을 확인할 수 있었습니다. textVisiblePassword가 가능한 이유는 inputType=text와 달리 한번 입력된 텍스트를 나중에 다시 입력할 때 편하게 입력할 수 있도록 입력 기록에 저장하는 경우가 있는데, "textVisiblePassword"을 사용하면 입력 기록에 저장하지 않는다고 합니다. 이러한 이유로 로그를 찍었을 시 source에 한 글자씩 들어올 수 있었던 것 같습니다.

 

위와 같이 inputType을 변경해 주는 방법도 있지만 비밀번호가 입력되는 칸이 아니기 때문에 상황에 맞지 않는 inputType은 선언하는 것보다 TextWatcher를 이용하여 입력 전 후에 필터링하는 방법을 이용할 수 도 있을 것 같습니다!

 

 

 

참고

https://latte-is-horse.tistory.com/285