티스토리 뷰
Compose에서 BottomSheet를 사용하는 방법은 2가지가 있습니다.
BottomSheetScaffold와 ModalBottomSheetLayout 두 가지 방식인데 둘의 차이점은 아래에서 다루도록 하겠습니다.
1. BottomSheetScaffold
val state = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)
val scope = rememberCoroutineScope()
BottomSheetScaffold(
scaffoldState = state,
sheetContent = {
BottomSheetContent(state)
},
sheetPeekHeight = 40.dp,
modifier = Modifier.fillMaxSize()
) {
MainContent {
scope.launch {
if (state.bottomSheetState.isCollapsed) {
state.bottomSheetState.expand()
} else {
state.bottomSheetState.collapse()
}
}
}
}
BottomSheetScaffold는 이름에서 알 수 있듯이 Scaffold의 확장형 버전입니다.
BottomSheet 기능 외에도 Topbar, Drawer를 추가할 수 있습니다.
사용 방법 역시 기본 Scaffold와 거의 동일합니다.
@Composable
fun MainContent(
onClickListener: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 20.dp, horizontal = 24.dp)
) {
Text(
text = "Bottom Sheet",
style = Typography.h4,
fontWeight = FontWeight.Bold
)
Button(onClick = onClickListener) {
Text(text = "버튼", style = Typography.body1)
}
}
}
content 블록은 메인으로 보이는 UI를 넣어주면 됩니다.
이번 예시에서는 Text와 Button으로 단순하게 표시하였습니다.
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun BottomSheetContent(state: BottomSheetScaffoldState) {
Card(
shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp),
border = BorderStroke(1.dp, Color.Black),
modifier = Modifier
.fillMaxWidth()
) {
Column(
modifier = Modifier.padding(horizontal = 20.dp)
) {
val rotate by animateFloatAsState(
targetValue = if (state.bottomSheetState.isCollapsed) 0f else 180f
)
Spacer(modifier = Modifier.height(8.dp))
Icon(
painter = painterResource(id = R.drawable.ic_arrow_up),
contentDescription = "",
tint = Color.Black,
modifier = Modifier
.rotate(rotate)
.align(Alignment.CenterHorizontally)
)
Spacer(modifier = Modifier.height(15.dp))
Text(text = "Bottom Sheet Scaffold", fontWeight = FontWeight.Bold)
Spacer(modifier = Modifier.height(15.dp))
Text(text = "Is Open")
Spacer(modifier = Modifier.height(30.dp))
}
}
}
sheetContent 영역에는 원하는 BottomSheet의 UI를 넣어주면 됩니다.
BottomSheet는 BottomSheetState를 통해 상태가 관리되며
val state = rememberBottomSheetScaffoldState(
bottomSheetState = BottomSheetState(BottomSheetValue.Collapsed)
)
rememberBottomSheetScaffoldState를 통해 변수를 생성할 수 있습니다.
초깃값으로 Collapsed와 Expanded를 사용할 수 있습니다.
scope.launch {
if (state.bottomSheetState.isCollapsed) {
state.bottomSheetState.expand()
} else {
state.bottomSheetState.collapse()
}
}
클릭 등의 이베트를 통해 BottomSheet의 state의 상태 값을 변경하기 위해서는
expand() 혹은 collapse()를 이용하면 됩니다.
두 함수는 suspend 함수이므로 코루틴이 필요합니다.
BottomSheetScaffold에서 BottomSheet를 관리하는 속성은 다음과 같습니다.
sheetGesturesEnabled
: BottomSheet를 제스처를 통한 상호작용 작동 여부sheetShape
: BottomSheet의 모양 설정sheetElevation
: BottomSheet의 그림자, 기본 값 8DpsheetBackgroundColor
: BottomSheet의 배경 색sheetContentColor
: BottomSheet의 컨텐츠 색상sheetPeekHeight
: BottomSheet를 접은 상태의 크기, 기본값 56Dp
2. ModalBottomSheetLayout
val modalState = rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipHalfExpanded = false
)
val scope = rememberCoroutineScope()
ModalBottomSheetLayout(
sheetState = modalState,
sheetContent = {
ModalBottomSheetContents()
}
) {
Column(
modifier = Modifier
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally
) {
ModalBottomSheetMain {
scope.launch {
modalState.show()
}
}
}
}
@Composable
fun ModalBottomSheetMain(
onClickListener: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 20.dp, horizontal = 24.dp)
) {
Text(
text = "Modal Bottom Sheet",
style = Typography.h4,
fontWeight = FontWeight.Bold
)
Button(onClick = onClickListener) {
Text(text = "버튼", style = Typography.body1)
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun ModalBottomSheetContents() {
LazyColumn {
items(50) {
ListItem(
text = { Text("Item $it") },
icon = {
Icon(
Icons.Default.Favorite,
contentDescription = "Localized description"
)
}
)
}
}
}
ModalBottomSheetLayout은 BottomSheetScaffold와 동일하게 content 영역과 sheetContent 영역을 구분을 두어서 UI를 구현하면 됩니다.
ModalBottomSheetState를 통해 상태가 관리되며 rememberModalBottomSheetState를 통해 변수를 생성할 수 있습니다.
ModalBottomSheetLayout은 3가지 상태 값을 가집니다.
- Hidden : 숨김 상태
- Expanded : 전체 펼쳐진 상태
- HalfExpanded : BottomSheet의 높이가 디바이스의 높이의 50%까지만 펼쳐진 상태
skipHalfExpanded를 True로 설정하면 HalfExpanded가 없이 2가지 상태로 관리할 수 있습니다.
이 외에도 animationSpec, confirmStateChange를 설정할 수 있습니다.
BottomSheet를 펼치기/접기 위해서는 위에서 만든 state의 show()/hide()를 이용하면 됩니다.
역시 suspend 함수이므로 코루틴이 필요합니다.
이 외에 ModalBottomSheetLayout에서 설정할 수 있는 속성들은 다음과 같습니다.
- sheetShape : BottomSheet의 모양
- sheetElevation : BottomSheet의 그림자, 기본 값 16Dp
- sheetBackgroundColor : BottomSheet의 배경 색상
- sheetContentColor : BottomSheet의 컨텐츠 색상
- scrimColor : BottomSheet Show 상태에서 BottomSheet 영역 외의 색상
BottomSheetScaffold와 ModalBottomSheetLayout의 가장 큰 차이점은 다이얼로그처럼 딤 효과의 유무와 접혀 있을 때 화면에 표시 가능 여부입니다.
두 개 다 사용해 보고 상황에 맞게 선택해서 사용하시기 바랍니다.
'안드로이드 > 코드' 카테고리의 다른 글
Compose 내 관리앱 만들기 : 1. 프로젝트 구성 (0) | 2023.03.19 |
---|---|
코드 분석 (0) | 2023.01.24 |
Compose QR코드 스캐너 (2) | 2022.11.04 |
Android Compose MotionLayout 2 (0) | 2022.11.03 |
Compose MotionLayout (0) | 2022.11.02 |
- Total
- Today
- Yesterday
- Duplicate class found error
- Compose 네이버 지도 api
- Compose BottomSheet
- Retrofit
- Pokedex
- Compose BottomSheetScaffold
- WorkManager
- 웹뷰
- Android
- column
- Compose MotionLayout
- WebView
- Compose QRCode Scanner
- Compose BottomSheetDialog
- 안드로이드 구글 지도
- Compose Naver Map
- Gradient
- 포켓몬 도감
- Row
- Android Compose
- Worker
- Compose ConstraintLayout
- Duplicate class fond 에러
- 안드로이드
- Fast api
- Kotlin
- LazyColumn
- Compose ModalBottomSheetLayout
- Compose 네이버 지도
- compose
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |