기록

CmplxN·2020년 12월 8일
0

스크롤 뷰 초기 위치 문제

한 화면 안에 모든 내용을 보이게 할 수는 없다.
그렇기 때문에 ScrollView를 이용해서 사용자가 현재 화면 밖의 화면을 볼 수 있게 구성한다.

사실 ScrollView 안에 있는 뷰들이 그나마 간단한 구조면 이럴 일은 거의 없다.
하지만 여러가지 뷰가 복합적으로 구성되다보면 최초 스크롤이 이상하게 되는 경우가 있다.
이런 현상이 기기 / 버전별로 상이하게 나타나서 찾기 어려울 수도 있다.

이 현상의 원인은 ScrollView 내부의 뷰가 포커스를 가져가는 것이었다.
ScrollView 내부의 일부 뷰가 뒤늦게 포커스를 가져갔고, 스크롤은 그 뷰로 가버린 것이다.
유저 입장에서는 화면에 진입했을 때 최상단이 아니면 이상하게 느낄 것이다.
그러므로 ScrollView 바로 아랫단의 레이아웃에 다음과 같은 attr을 준다.

android:descendantFocusability="blocksDescendants"

말그대로 자식으로의 포커스를 block해버리는 방법이다.

터치 이벤트 전달

복잡한 UI를 구성하다보면 여러가지 뷰들이 서로 겹친다.
이렇게 한곳에 여러 계층으로 되어있는 뷰가 있으면 터치 이벤트는 어떻게 처리될까?

이것에 대해 자세하게 설명하면 말이 길어지므로 간단히 얘기하자면,
최상위 부모에서 마지막 자식까지 touch정보가 전달된 다음, 아래에서 위로 올라가는 순서로 이벤트가 처리된다.

이 흐름을 개발자가 제어할 수 있는데,
onInterceptTouchEvent()의 리턴값으로 자식으로 내려가는 것(Notify)을 차단할 수 있다.
또한, onTouchonTouchEvent()의 리턴값으로 부모로 올라가는 것(Handle)을 차단할 수 있다.
아래 이미지와 링크를 참조하자.

적용

실제 하다가 겪은 문제를 살펴보자.
LinearLayout 위에 적당한 패딩을 두고 RecyclerView가 있다.
그리고 Layout에 클릭 이벤트를 걸어놓는다고 하자.
이때 RecyclerView의 item에 click은 아무 효과가 없었다.

RecyclerView의 item마다 LinearLayout에 걸었던 이벤트를 걸어줄 수도 있다.
하지만, 그렇게하면 그 이벤트만 발생하는 것이지, 원래 LinearLayout을 터치했을 때의 효과는 잃는다.
예를들면 LinearLayout 백그라운드 selector drawable이 pressed에 따라 효과가 있을 때,
RecyclerView item에 이벤트를 주는 것으로는 기대하는 pressed 효과가 생기지 않는다.

그러므로, 이때 아래처럼 커스텀 LinearLayout을 만들고 onInterceptTouchEvent()를 오버라이드하면 된다.

class MyLinearLayout @JvmOverloads constructor(
        context: Context,
        attributes: AttributeSet? = null,
        defStyle: Int = 0
) : LinearLayout(context, attributes, defStyle) {

    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        return true
    }
}

onInterceptTouchEvent()가 true기 때문에 touch 이벤트는 child(여기선 RecyclerView)로 내려가지 않는다.
그래서 더이상 item클릭이 아닌 LinearLayout의 touch(click)으로 인식된다.

R파일 확인하기

android.content.res.Resources$NotFoundException: Resource ID N
개발을 하다보면 위와 같은 런타임 에러를 만날 수 있다. (리소스 아이디는 16진수로 나올 것이다.)

이 에러로그를 보면 무엇이 하고싶은가?
대충 보면, 리소스 아이디에 대한 리소스를 찾지 못한다는 것이므로 리소스에 문제가 있는 것일 것이다.
그러므로 당연히도 해당 Resource ID가 어떤 리소스 인지 궁금할 것이다.

사실 리소스를 전달하는 메소드는 평소에 많이 쓰기때문에 리소스 -> ID는 익숙하다.
그러나 ID -> 리소스는 익숙하지 못한 편이다.
그래서 맞닥뜨리기 이런 에러를 전에는 R.java를 직접 찾아볼 일은 거의 없다.
그러면 어떻게 ID -> 리소스를 알아볼 수 있는지 보자. (Android Studio 4.1.0)

따라가기

먼저 아래와 같이 좌상단에서 항목을 Project로 바꾼다.
그리고 app - build - outputs - apk - debug(디버그 빌드인 경우)에 있는 apk를 연다.

그다음 classes2.dex를 연다.

dex파일을 열면 안에 R 관련 클래스들이 종류별로 정리되어있다.

원하는 종류별 R 클래스에서 우클릭 - Show ByteCode를 열면 ID -> 리소스를 알 수 있다.

profile
Android Developer

0개의 댓글