본문 바로가기
Jetpack Compose

[Jetpack Compose] Compose로 BottomSheet 구성하기 feat. Material 3

by JongSeok 2024. 1. 16.

Jetpack Compose로 BottomSheet를 구성하는 방법을 찾아보면서 효과적이라고 생각되는 두 가지 방법을 공유합니다 :)

MaterialDesign3 환경에서 작성되었습니다.

Jetpack compose material 3 bottom sheet

 


1. ModalBottomSheetLayout

ModalBottomSheetLayout 정의

ModalBottomSheetLayoutBottomSheet의 UI를 구성하는 sheetContent 컴포저블 함수
BottomSheet를 포함하는(?), BottomSheet가 띄워질(?) 상위 스크린을 구성하는 content 컴포저블 함수로 구성할 수 있습니다.

그 외에 속성들을 생성자로 설정하지 않으면 기본값으로 지정된 BottomSheet 속성으로 적용되지만 여러 속성들을 통해 BottomSheet의 배경색, 모양, 최초 상태 등을 정의할 수 있습니다.

ModalBottomSheetLayout와 유사한 BottomSheetScaffold라는 클래스가 있는데 이 둘의 차이는 BottomSheet와 BottomSheet를 포함하는 스크린과의 상호작용이 가능한지의 여부입니다.
ModalBottomSheetLayout은 시트가 펼쳐진 상태가 되면 BottomSheet 외부 영역인 상위 스크린이 살짝 가려진 어두워진 처리가 되면서 외부 영역을 터치하면 시트가 닫히게 됩니다. 닫힐지의 여부 또한 설정할 수 있습니다.

그에 반해 BottomSheetScaffold는 BottomSheet가 항상 유지되어 시트가 펼쳐지더라도 상위 스크린을 가리지 않고 상위 스크린과 시트를 오가면서 자유롭게 터치가 가능하다는 차이가 있습니다. (카카오맵의 홈화면이 이런식으로 구현되어 있는 것 같네요)

 

ModalBottomSheetLayout(
    sheetContent = {
    	// BottomSheet를 구성하는 UI      
        ...
    }
) {
    // BottomSheet를 띄울 전체 스크린을 구성하는 UI
    ...
}

ModalBottomSheetLayout의 가장 간단한 형태로는 위와 같은 코드로 구현할 수 있습니다.

 

'ModalBottomSheetLayout의 예시'의 코드

이 때 MainLayout은 BottomSheet가 열리는 상위 스크린을 구성하는 UI 컴포넌트입니다.

ModalBottomSheetLayout의 예시

sheetContent 블럭을 아직 텍스트 두 줄로만 구성해 어색하지만 UI를 얼마든지 추가할 수 있습니다.

여러 속성들과 State가 적용된 모습입니다.

 

특정 영역을 터치 시 위에서 작성한 BottomSheet를 펼치기 위해서는 다음과 같은 방법으로 열 수 있습니다.

 

2. ModalBottomSheet

1번 ModalBottomSheetLayout에서 'Layout'이 빠진 ModalBottomSheet입니다.

대부분이 유사하지만 ModalBottomSheetLayout에서는 BottomSheet의 UI와 BottomSheet가 펼쳐지는 상위 스크린의 UI를 모두 ModalBottomSheetLayout 클래스 내부에서 작성했다면 ModalBottomSheet는 BottomSheet의 UI만을 구성한다는 차이가 있습니다.

ModalBottomSheet 클래스를 이용한 코드

...
// isEmotionBottomSheetOpen가 true라면 BottomSheet 펼치기
var isEmotionBottomSheetOpen by remember { mutableStateOf(false) }

...
if (isEmotionBottomSheetOpen) {
    EmotionBottomSheet(
        closeSheet = { isEmotionBottomSheetOpen = false }
    )
}

 

실행 결과는 ModalBottomSheetLayout 클래스를 사용했던 결과와 동일합니다.

 

dragHandle 속성을 null로 지정해 준 이유는 null로 지정하지 않는다면 BottomSheet 상단에 기본적으로 상단바와 일정한 공간을 차지하도록 구성됩니다.

저는 상단바를 제거하기 위해 dragHandle을 null로 설정했지만 dragHandle 속성을 활용하면 Sheet를 위아래로 drag(드래그)하는 상황을 커스텀할 수 있습니다.

 

상위 스크린을 구성하는 코드와 분리되어 별도의 컴포저블 함수로 존재하기 때문에 자주 쓰이는 BottomSheet마다 타입을 지정해 컴포넌트화할 수 있어 재사용성의 측면에서 훨씬 쉽고 편리한 것 같습니다.

 

Compose로 개발하면서 BottomSheet를 어떻게 구성할 수 있을까 찾아보던 중 ModalBottomSheetLayout을 발견해 처음에는 ModalBottomSheetLayout로 BottomSheet를 구성했습니다.

하지만 상위 컴포넌트가 하위 컴포넌트를 종속되는 것 같아 더 좋은 방법은 없을까 고민하던 중 ModalBottomSheet가 최신 Material3 버전에 추가되어 공부해 보았습니다. :)

 

728x90
반응형