BottomSheetDialog 함수는 Compose를 사용하여 바텀 시트 다이얼로그를 생성하는 역할을 하며, 바텀 시트 다이얼로그를 표시하여 사용자가 특정 항목을 제거하거나 취소할 수 있도록 한다.
sheetState를 통해 다이얼로그의 상태를 관리하고, onRemoveClickListener와 dismissBottomSheet를 통해 사용자 인터랙션을 처리한다.
BottomSheetDialog의 주요 요소 및 역할
- 매개변수
onRemoveClickListener: (SearchModel) -> Unit
: 사용자가 항목 제거 버튼을 클릭했을 때 호출되는 콜백 함수로 제거할 항목을 인자로 받는다.searchModel: SearchModel
: 현재 선택 된 SearchModel 객체로 다이얼로그가 어떤 항목을 대상으로 동작하는지 알기 위해 사용된다.dismissBottomSheet: () -> Unit
: 다이얼로그를 닫기 위한 함수로 사용자가 다이얼로그 외부를 클릭하거나 취소 버튼을 클릭했을 때 호출된다.- 상태 관리
val sheetState = rememberModalBottomSheetState()
: 바텀 시트의 상태를 관리하기 위한 상태 객체로 다이얼로그의 열림/닫힘 상태를 추적한다.- ModalBottomSheet
onDismissRequest = dismissBottomSheet
: 사용자가 다이얼로그 외부를 클릭했을 때 다이얼로그를 닫는 함수이다.sheetState = sheetState
: 바텀 시트의 상태를 전달한다.
@Composable
fun GradientProvider(): List<Color> { // 색상 목록을 반환
return listOf(
colorResource(id = R.color.color_1), // 첫 번째 색상
colorResource(id = R.color.color_2), // 두 번째 색상
colorResource(id = R.color.color_3) // 세 번째 색상
)
}
// ExperimentalMaterial3Api를 옵트인하여 사용
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetDialog(
onRemoveClickListener: (SearchModel) -> Unit, // 항목 제거 버튼 클릭 시 호출되는 함수
searchModel: SearchModel, // 현재 선택된 SearchModel 객체
dismissBottomSheet: () -> Unit, // 바텀 시트를 닫는 함수
) {
val sheetState = rememberModalBottomSheetState() // 바텀 시트의 상태를 기억하기 위한 변수
ModalBottomSheet(
onDismissRequest = dismissBottomSheet, // 바텀 시트 외부를 클릭했을 때 닫히도록 설정
sheetState = sheetState, // 바텀 시트 상태
shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp), // 바텀 시트의 모서리 모양
contentColor = Color.White, // 내용물 색상
dragHandle = null, // 드래그 핸들 비활성화
modifier = Modifier.fillMaxWidth() // 바텀 시트의 너비를 화면 가득 채우기
) {
Column(
modifier = Modifier
.background(color = Color.White), // 배경색 설정
verticalArrangement = Arrangement.Center, // 수직 중앙 정렬
horizontalAlignment = Alignment.CenterHorizontally // 수평 중앙 정렬
) {
// 제목 텍스트
Text(
text = stringResource(id = R.string.storage_bottom_sheet_title),
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.padding(top = 12.dp, bottom = 12.dp)
)
// 메시지 텍스트
Text(
text = stringResource(id = R.string.storage_bottom_sheet_message),
fontSize = 14.sp,
textAlign = TextAlign.Center,
modifier = Modifier.padding(bottom = 12.dp)
)
Row(
modifier = Modifier.fillMaxWidth(), // 너비를 화면 가득 채우기
horizontalArrangement = Arrangement.Center
) {
Button(
onClick = {
dismissBottomSheet() // 취소 버튼 클릭 시 바텀 시트 닫기
},
modifier = Modifier
.weight(1f) // 버튼 너비를 동일하게 설정
.padding(start = 12.dp, end = 4.dp), // 패딩 설정
colors = ButtonDefaults.buttonColors(backgroundColor = colorResource(id = R.color.color_1)), // 버튼 배경색 설정
shape = RoundedCornerShape(32.dp), // 버튼 모서리 모양 설정
border = BorderStroke(
width = 1.dp, // 테두리 두께
color = colorResource(id = R.color.color_1) // 테두리 색상
)
) {
Text(
text = stringResource(id = R.string.bt_cancel), // 취소 버튼 텍스트
color = Color.White // 텍스트 색상
)
}
Spacer(modifier = Modifier.width(16.dp)) // 버튼 간 간격
Button(
onClick = {
onRemoveClickListener.invoke(searchModel) // 제거 버튼 클릭 시 호출
dismissBottomSheet() // 바텀 시트 닫기
},
modifier = Modifier
.weight(1f) // 버튼 너비를 동일하게 설정
.padding(start = 4.dp, end = 12.dp, bottom = 12.dp), // 패딩 설정
colors = ButtonDefaults.buttonColors(backgroundColor = Color.White), // 버튼 배경색 설정
shape = RoundedCornerShape(32.dp), // 버튼 모서리 모양 설정
border = BorderStroke(
width = 1.dp, // 테두리 두께
brush = Brush.linearGradient( // 선형 그라디언트 브러쉬 설정
colors = GradientProvider(), // 그라디언트 색상 목록
start = Offset.Zero, // 시작 오프셋
end = Offset.Infinite // 종료 오프셋
)
)
) {
Text(
text = stringResource(id = R.string.bt_remove), // 제거 버튼 텍스트
color = colorResource(id = R.color.color_1)
)
}
}
}
}
}
StorageScreen 함수는 Compose를 사용하여 저장된 항목 목록을 표시하고 사용자가 특정 항목을 클릭했을 때 바텀 시트 다이얼로그를 표시하는 역할을 한다.
StorageScreen의 주요 요소 및 역할
- ViewModel
val searchState by viewModel.storageItems.observeAsState()
: StorageViewModel의 storageItems을 관찰하여 저장된 항목 목록의 상태를 searchState로 가져온다.var bottomSheetState by remember { mutableStateOf(BottomSheetState()) }
: 바텀 시트의 상태를 관리하기 위한 bottomSheetState 변수를 초기화한다. 바텀 시트의 열림 여부와 선택된 항목을 저장한다.- LaunchedEffect
LaunchedEffect(viewModel)
: viewModel이 초기화될 때 호출되어 viewModel.getStorageItems()를 통해 저장된 항목을 가져온다.- SearchList 컴포저블
- 저장된 항목을 표시하며 searchState를 통해 항목 목록을 가져오고, 사용자가 항목을 클릭했을 때 bottomSheetState를 업데이트하여 바텀 시트를 연다.
// BottomSheetState 데이터 클래스는 바텀 시트의 상태를 관리
data class BottomSheetState(
val isOpen: Boolean = false, // 바텀 시트 열림 여부
val searchModel: SearchModel? = null // 선택된 SearchModel 객체
)
@Composable
fun StorageScreen(viewModel: StorageViewModel = hiltViewModel()) {
val searchState by viewModel.storageItems.observeAsState() // 저장된 항목 상태 관찰
var bottomSheetState by remember { mutableStateOf(BottomSheetState()) } // 바텀 시트 상태 기억
// viewModel이 초기화될 때 호출
LaunchedEffect(viewModel) {
viewModel.getStorageItems() // 저장된 항목을 가져오는 함수 호출
}
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.White)
) {
SearchList(
items = searchState ?: emptyList(), // 검색 항목 목록
onItemClick = { searchModel ->
bottomSheetState = BottomSheetState(isOpen = true, searchModel = searchModel) // 항목 클릭 시 바텀 시트 열기
},
onScrollEnd = { viewModel.getStorageItems() } // 스크롤 끝에 도달 시 추가 항목 가져오기
)
}
if (bottomSheetState.isOpen) { // 바텀 시트가 열려 있을 때
val currentSearchModel = bottomSheetState.searchModel ?: error("searchModel is null") // 현재 선택된 SearchModel 객체
BottomSheetDialog(
onRemoveClickListener = {
viewModel.removeStorageItem(currentSearchModel) // 항목 제거 함수 호출
bottomSheetState = BottomSheetState() // 바텀 시트 상태 초기화
},
searchModel = currentSearchModel, // 현재 선택된 SearchModel 객체 전달
dismissBottomSheet = { bottomSheetState = BottomSheetState() } // 바텀 시트 닫는 함수
)
}
}