본문 바로가기
Android/Open Source

[Open Source] KoreanNumberFormatter 라이브러리

by 준그래머 2023. 7. 20.
반응형

개발 동기

내부 라이브러리 클래스 중 PhoneNumberUtils가 존재하는데, 보통 번호 포맷을 적용하기 위해 쓰인다. 문제는 format 함수에 재난망 번호인 013 번호 체계가 존재하지 않아 포맷이 적용되지 않는 이슈가 있었다. 때문에 단말기의 지역이 한국인 경우 새로 만든 KoreanNumberFormatter 클래스를 이용해 번호를 반환해주기 위해 만들었다.

 

소개

Android Studio에서 Java를 이용해 제작했으며 번호 체계는 전기통신번호관리세칙, 대한민국의 전화번호 체계, 나무위키 전화번호 를 참고해 구현했다.

클래스는 KoreanNumbers, KoreanNumberFormatter, KoreanNumberEditText 총 3가지로 구성되어 있다.

먼저 KoreanNumbers는 한국 번호 체계에 대해 데이터를 갖고 있는 클래스로 아래처럼

// 01A-XXXX-XXXX
@NonNull public static final Map<String, String> MOBILE_NUMBERS = new HashMap<>(); 
...
static {
    // 이동통신 및 부가통신망 등 (01A-XXXX-XXXX)
    MOBILE_NUMBERS.put("010", "이동전화");
    MOBILE_NUMBERS.put("011", "이동전화 (SK텔레콤)");
    MOBILE_NUMBERS.put("012", "사물통신");
    MOBILE_NUMBERS.put("013", "재난안전통신망");
    MOBILE_NUMBERS.put("015", "무선호출");
    MOBILE_NUMBERS.put("016", "이동전화 (KT)");
    MOBILE_NUMBERS.put("017", "이동전화 (SK텔레콤)");
    MOBILE_NUMBERS.put("018", "이동전화 (KT)");
    MOBILE_NUMBERS.put("019", "이동전화 (LG유플러스)");
    ...
}

 

포맷 데이터를 HashMap으로 저장하고 있으며

 

public static boolean containMobileNumber(@NonNull String number){
    for(String mobilNumber: KoreanNumbers.MOBILE_NUMBERS.keySet()){
        if(number.startsWith(mobilNumber)) return true;
    }
    return false;
}

포맷이 HashMap에 존재하는지 확인 하는 함수를 갖고 있다.

 

데이터 및 함수를 이용해 포맷 적용하고 사용자에게 반환 해주는 클래스는 KoreanNumberFormatter이며

@NonNull
public static String formatNumber(@NonNull String text){
    SpannableStringBuilder spannable = new SpannableStringBuilder(text);
    format(spannable);
    return spannable.toString();
}

formatNumber를 통해 사용자는 형식이 적용된 텍스트를 반환 받을 수 있다.

 

마지막으로 KoreanNumberEditText는 안드로이드 앱을 위핸 클래스로 EditText를 상속 받아 입력된 데이터가 포맷이 적용된 텍스트로 변환되도록 만든 클래스다.

private final TextWatcher textWatcher = new TextWatcher() {
    boolean isSubtract = false;
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        isSubtract = count != 0 && after == 0;
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        String formatText = formatNumber(s.toString());
        if(!formatText.contentEquals(s)){
            int sHyphenLength = s.toString().replaceAll("[0-9]", "").length();
            int formatHyphenLength = formatText.replaceAll("[0-9]", "").length();
            Log.d(TAG, "onTextChanged: sHyphenLength=" + sHyphenLength + ", formatHyphenLength=" + formatHyphenLength);
            int selectionStart;
            if(isSubtract){
                selectionStart = getSelectionStart();
                // 0135203011222| 이 상태에서 삭제한 경우 하이픈이 2개 생기므로 selection 포지션을 2 더 해줘야함
                if(sHyphenLength==0 && formatHyphenLength==2 && selectionStart == s.length()){
                    selectionStart += 2;
                }
            }
            else{
                // 0|352030112 이 상태에서 1을 입력하면 하이픈이 2개 생긴 경우나 01|3-5203-0112 에서 1을 삭제하는 경우 하이픈이 2개 삭제되는 경우 selection의 포지션 변경이 필요 없다.
                if((sHyphenLength==0 && formatHyphenLength==2) || (formatHyphenLength==0 && sHyphenLength==2)){
                    selectionStart = getSelectionStart();
                }
                else{
                    // 013| 이 상태에서 입력하는 경우 하이픈이 증가하는 수 만큼 selection의 위치를 옮겨줘야한다.
                    selectionStart = getSelectionStart() + formatHyphenLength - sHyphenLength;
                }
            }
            setText(formatText);
            setSelection(Math.min(selectionStart, formatText.length()));
        }
    }
    @Override
    public void afterTextChanged(Editable s) {}
};

 

결과

코드

 

GitHub - JunYou-Park/KoreanNumberProject: 한국 번호 체계에 따른 번호 세팅을 위해 만든 라이브러리 겸 프

한국 번호 체계에 따른 번호 세팅을 위해 만든 라이브러리 겸 프로젝트. Contribute to JunYou-Park/KoreanNumberProject development by creating an account on GitHub.

github.com

 

반응형