Android

[Android/정규식] 특정 양식의 전화번호만 링크로 처리

Question영 2023. 1. 5. 18:47
반응형

※ 해당 글은 제가 직접 작성한 글입니다. 정확하지 않은 정보일 수 있으니 정정할 사항이 있으면 알려주시기 바랍니다.

※ 스크랩이나 담아갈시 댓글에 출처를 남겨주세요.

 

목적

  • 문장에서 전화번호만 추출하여 이벤트를 부여하거나 편집하고 싶을 경우 진행

 

환경

  • Macbook
  • Android Studio

 

용어

  • 정규식(정규표현식)
    • 프로그래밍에서 문자열을 다룰 때, 문자열의 일정한 패턴을 표현하는 일종의 형식 언어를 말한다. 정규식이라고도 부르며,보통 regex 혹은 regexp라 많이 쓴다. (나무위키)

 

테스트 데이터

010-1234-1234전화번호테스트1234-1234전화번호 테스트1234-1234전화번호 테스트
전화번호 케이스 1 : (1234-1234)
전화번호 케이스 2 : 1234-12341234
전화번호 케이스 3 : 32432431234-1234
전화번호 케이스 4 : zzzzz1234-1234테스트
전화번호 케이스 5 : 1234 1234
전화번호 케이스 6 : 테스트 1234 1234테스트
전화번호 케이스 7 : 1234 1234테스트
url 테스트 https://www.naver.com (1234-1234)
010 4444 4444
adfadf010 4444 4444dsafsfa
dfafada010 4444 4444
(010 4444 4444)

준비한 테스트 데이터는 영문 한글 전화번호 숫자양식등을 고려하여 임의 작성

 

검증 진행

  • regexr 사이트에서 테스트를 진행

 

사용 정규식

1. ex) 1234-1234

(?=\d{4}.?\d{4}[\D]).*?((?<=[\D])\d{4}.?\d{4})

 

2. ex) 010-1234-1234

(?=(\d{3}(\s|-))?\d{4}(\s|-)\d{4}(\D|$)).*?((?<=(\D|^))\d{4}(\s|-)\d{4})

 

정규식 작성 고려사항

  • 숫자와 숫자 사이에 띄어쓰기나 - 같은 표현을 고려하여 정규식을 작성
  • .*? 표현은 AND 와 같은 의미

 

Android 에서 위의 정규식이 필요한 경우와 해결 방법

  • 현재 기준 Android TextView 에서 ellipse 기능과 AutoLink 기능을 동시에 사용하려고 할때 문제가 발생함 (동시 사용 안됨)
  • Layout XML 에서 TextView 에 limitLine = "2", ellipze ="end" 옵션을 설정
  • Link 는 Kotlin 혹은 Java 에서 적용 처리
// 처리 본문
val spanText = SpannableString(item.description)
Linkify.addLinks(spanText, Linkify.ALL)
tvDescription.text = spanText
tvDescription.setOnTouchListener(TouchTextView(spanText))
// TouchTextView
class TouchTextView(
    var spannable: Spannable,
    val clickUrl: (URLSpan) -> Unit
) : View.OnTouchListener {

    override fun onTouch(v: View, event: MotionEvent): Boolean {
        val action = event.action
        if (v !is TextView) {
            return false
        }
        if (action == MotionEvent.ACTION_UP ||
            action == MotionEvent.ACTION_DOWN
        ) {
            var x = event.x.toInt()
            var y = event.y.toInt()
            x -= v.totalPaddingLeft
            y -= v.totalPaddingTop
            x += v.scrollX
            y += v.scrollY
            val layout = v.layout
            val line = layout.getLineForVertical(y)
            val off = layout.getOffsetForHorizontal(line, x.toFloat())
            val link = spannable.getSpans(
                off, off,
                ClickableSpan::class.java
            )
            if (link.isNotEmpty()) {
                when(action) {
                    MotionEvent.ACTION_UP -> {
                        val linkUrl = (link[0] as URLSpan)
                        if (linkUrl.url.startsWith("tel:")) {
                            link[0].onClick(v)
                        } else {
                            clickUrl.invoke(linkUrl)
                        }
                        v.performClick()
                    }
                    MotionEvent.ACTION_DOWN -> {
                        Selection.setSelection(
                            spannable,
                            spannable.getSpanStart(link[0]),
                            spannable.getSpanEnd(link[0])
                        )
                    }
                    else -> {}//Nothing
                }
                return true
            } else {
                Selection.removeSelection(spannable)
            }
        }
        return false
    }
}

 

마치며

리스트 형태의 화면에서 전화번호에 이벤트 부여를 위해 많이 사용될 것으로 기대 되며,실제로 맡은 프로젝트를 진행하면서 사용했던 방법으로 IOS 에서도 정규식은 그대로 사용하면 됩니다.
정규식의 해석은 구글링하면 많이 나와 있으니 별도로 다루지 않도록 하겠습니다.

 

참고

반응형