[안드로이드/코틀린] 특정 뷰가 화면에서 가려지는지 여부를 동적으로 확인하기
특정 뷰가 사용자에게 보여지지 않을 때를 처리할 경우가 있다.
안드로이드 View 클래스에 onWindowVisibilityChanged 라는 리스너가 있었는데,
xml이나 코드 상에서 뷰의 visibility 자체를 GONE, INVISIBLE, VISIBLE로 변경하는 경우에만 호출이 되었다.
(참고: https://developer.android.com/reference/android/view/View#onWindowVisibilityChanged(int))
하지만 visibility는 변하지 않고 다른 뷰에 의해 가려지거나 스크롤 액션에 의해 가려지는 경우를 특정하고 싶었다.
그래서 디바이스 화면 자체에서 뷰의 x, y 좌표를 구하고, 그 좌표가 음수값인지 아닌지에 따라 hide 여부를 판별했다.
안드로이드의 좌표는 화면 가장 상단 왼쪽부터 (0, 0)이고 하단 오른쪽으로 갈 수록 x, y 값이 커지므로
x, y 중 하나라도 음수가 나온다면 화면의 좌표를 벗어난 것이므로 따로 이벤트 처리를 해주었다.
디바이스의 x, y 좌표 구하는 코드
val location = IntArray(2)
뷰.getLocationOnScreen(location)
val x = location[0]
val y = location[1]
if (x < 0 || y < 0) // 뷰가 화면에서 가려진 경우
else // 뷰가 화면에 보이는 경우
getLocationOnScreen()을 호출하면 인자로 전달한 IntArray에 뷰의 현재 좌표 x, y 값이 들어간다.
val y = IntArray(2).run {
뷰.getLocationOnScreen(this)
this[1]
}
코틀린 내장 함수를 활용하여 간단하게 표현할 수 있다.
만약 다른 뷰에 의해 가려지는 경우를 판단하고 싶은 경우
다른 뷰의 width, height를 뺀 값이 음수인지 비교하면 된다.
나는 스크롤뷰 안에서 스크롤할 때마다 TextView가 가려지는지 확인하기 위해 아래와 같은 코드를 사용했다.
scrollView.setOnScrollChangeListener { _, _, _, _, _ ->
val textViewY = IntArray(2).run {
binding.textView.getLocationOnScreen(this)
this[1]
}
if (textViewY < 0) // 뷰가 가려질 때의 이벤트 처리
else // 뷰가 보일 때의 이벤트 처리
}