⬛️ Compose 에서 전체 Dim 처리

David·2024년 12월 14일
0

[Android] Compose

목록 보기
6/6
post-thumbnail

Dim 처리 해주세요 🥹

dim 처리가 일부분 안 되는 것을 확인하여 FAB 영역을 제외한
나머지 영역을 전부 dim 처리 요청을 받았는데요.

당시 해당 부분을 구현할 때는
FAB 클릭 여부를 최상위 상태로 호이스팅 하여

  • TopBar
  • StatusBar
  • 지도 영역 (Box Layout으로 덮어쓴)

3개의 섹션을 위 상태를 바라보게 만들어
색상을 변경하며 dim 처리와 유사하게 만들었습니다.

🤔 위 방법으로 처리 시 몇 가지 이슈가 있었습니다.

⚠️ 첫 번째, 색상 설정

상태가 dim 처리로 변경 시
해당 컴포넌트 컨테이너와 컨텐츠 색상을
일일이 변경해줘야 합니다.

⚠️ 두 번째, 다른 UI 시스템(Xml, Compose)

위 영역은 전부 Compose 인데
바텀메뉴(바텀 탭, 바텀 네비게이션) 부분은
xml 형태의 BottomNavigationView 를 사용하고 있습니다.

(이를 인터페이스로 연결하여 해결할 수 있지만
BottomNavigationView의 컨테이너 색상과 item 색상을 일일이
상태에 따라 바꿔줘야 하는 번거로움이 있습니다)

⚠️ 세 번째, 부 자연스러움

상태를 바라보는
각 컴포넌트가 각자
바뀌는 형식으로 구현되어 있어
dim 상태로 바뀌는 것이
자연스럽지 않습니다.

⚠️ 네 번째, 코드 퀄리티 유지보수의 복잡

다른 UI 컴포넌트가 지도 위에 추가된다면
해당 컴포넌트에 대해서 dim의 추가 처리가 필요하고
지도위의 Box 영역을 고려하여
순서를 신경써서 개발해야 합니다.


위 이슈들로
결국 다른 방법으로 dim 처리를 해야겠다고
결심 했습니다.


🔎 Root View 를 찾아서(feat. Window)

처음에는 common 케이스라고 생각하여
검색을 좀 해봤는데 쉽게 찾아지지 않았습니다.


이런저런 시도 및 고민을 거듭한 끝에

💡 아예 루트 화면을 dim 색상으로 뒤 덮을 수 없나?

라는 생각을 시작했고
이에 다시 Window 개념을 찾아보기 시작했습니다.


Activity 코드를 보면 내부적(internal)으로 attach 하면서
Window 객체를 할당하고

해당 PhoneWindow 에서는
🔎 Decorview 로 RootView를 가지고 있는 모습을 띕니다.

위의 관계를 시각화 하면
(StackOverFlow에서 돌아다니는)
hierarchy 를 볼 수 있습니다.

제가 원하는 것은
StatusBar 및 BottomNavigationView 까지 전부
dim 처리가 된 화면이므로
DecorView (root) 위에
dim 처리 된 View를 올리면 됩니다.


🔳 Compose 에서 DecorView 위에 Dim 올리기

처리 흐름은 다음과 같습니다.

  • Dim 처리가 된 View 를 생성한다
  • FAB 버튼의 Window 위치를 바탕으로 Dim 처리된 뷰에 구멍(?)을 뚫는다
  • FAB 버튼을 클릭하면 Activity 의 window 를 가져와서 DecorView 위에 Dim View 를 추가 및 제거한다.
  • 해당 화면을 나가면 역시 Dim View 를 제거한다.

🌱 Dim View 생성

위 코드를 보면 그릴 때
Rect 추가(Dim 영역)
Oval(Fab Button), RoundRect(Fab Menu Container)를 그리는데요

아래 두 개의 Oval, RoundRect 가 구멍을 뚫는 부분 입니다.
여기서 Canvas 의 개념을 알아야 하는데요

  • CW (Clockwise): 시계 방향
  • CCW (Counter-Clockwise): 반시계 방향

두 코드를 보면 마지막 인자에 Path.Direction.CCW 로 설정하면서
상대적으로 뚫는 연출이 됩니다.

🌱 FAB 버튼 Window 위치

🌱 Window 가져오기

  • 해당 컴포저블에서 window 를 가져올 때 Preview 화면에서 그리지 못 하기 때문에
    nullable 하게 생성

🌱 dim 처리 적용 및 해제

  • 위에 선언된 window 로 부터 decorView 를 가져와서 그 위에 addView, removeView
  • Preview로 인해서 window 가 nullable 한 객체이므로 null 일 때
    DisposableEffect early return 구현

🚀 위의 방법을 적용한 dim 결과


👇🏻 dim 에서 특정 영역만 터치 가능하게 만들기

특정 영역에서 터치를 가능하게 만들려면
1. 특정 영역의 위치 파악
2. 터치 좌표 파악
3. 특정 영역이 아니면 터치 이벤트 전파 X

위 조건을 만족하려면 우선 dispatchTouchEvent()를 알아야 합니다.

dispatchTouchEvent는 그림과 같이 가장 상위 Activity 부터 내려오는데

📌 만약 false를 리턴하면 소비가 되지 않아 하위 뷰로 전달되고
📌 만약 true를 리턴하면 소비가 되어 더이상 하위 뷰로 touchEvent가 전달되지 않습니다.
( 3번은 위 개념으로 해결)

그러면 1번과 2번은 어떻게 해결할까요?

1번과 2번은 같이 엮일 수 있는데요

1번의 특정 영역 위치는 이미 위에서
columnBounds, circleBounds로 위치를 받았습니다.

2번은 dispatchTouchEvent에서 parameter로 event가 내려오기 때문에
event 위치로 파악이 가능합니다.

그러면 1번과 2번을 조합하여 다음과 같이 개발할 수 있습니다.

👋🏻 포스팅을 마치며

Compose 에서 Dim 처리를 해봤습니다.
common한 케이스인줄 알았고 쉽게 처리할 수 있다고 생각했는데
그렇지 않아 생각보다 시간이 좀 들었습니다.
그렇지만 dim 처리를 하면서
Window 개념을 조금 더 확실하게 알아보는 계기가 되었고
안드로이드 베이스가 조금 더 탄탄해진 것 같아
의미있는 시간이였습니다.

최근에 지도 디벨롭 버전을 개발하느라
정신이 없는데
아마 다음 포스팅은
커스텀 바텀시트에 대해 정리할 것 같습니다.
감사합니다!

profile
공부하는 개발자

0개의 댓글

관련 채용 정보