#1 개요
레코드를 INSERT하는 버튼과 DELETE하는 버튼을 각각 구현한다.
#2 코드 - 깨알 수정
...
@Composable
fun NutrientScreen(
...
) {
...
LazyColumn(
...
) {
...
itemsIndexed(...) { ... ->
Card(
...
elevation = CardDefaults.cardElevation(4.dp)
) {
...
}
}
}
}
레코드 하나하나를 감싸는 Card의 그림자값을 줄인다. 그림자값이 8.dp면 다른 카드 영역에까지 그림자가 침범해버리기 때문이다.
TMI
지금은 기능 구현 위주로만 개발한다. 사용자의 만족감을 끌어올리기 위한 시각적 작업은 막판에 몰아서, 프론트엔드를 완전히 갈아엎는 방식으로 수행할 것이다. 따라서 이런 깨알 같은 수정 사항에 큰 의미는 없다. 다만, 과정이 보기 좋고 즐거워야 더 몰입되고, 프로젝트에 애정도 생길 것이다.
#3 코드 - INSERT 버튼
#3-1 모양 잡기
...
@Composable
fun NutrientScreen(
...
) {
...
LazyColumn(
...
reverseLayout = true
) {
item {
FilledTonalButton(
onClick = {
// TODO
},
modifier = Modifier
.fillMaxWidth()
.padding(
start = 8.dp,
top = 0.dp,
end = 8.dp,
bottom = 8.dp
),
shape = CardDefaults.shape,
elevation = ButtonDefaults.filledTonalButtonElevation(4.dp)
) {
Text(
text = "+",
fontSize = 30.sp
)
}
}
...
itemsIndexed(...) { ... ->
...
}
}
}
LazyColumn에 item { ... } 영역을 선언하고, 그 안에 FilledTonalButton을 넣는다. LazyColumn의 reverseLayout 프로퍼티에 true를 대입했으므로, 아이템들은 역순으로 정렬된다. 따라서, LazyColumn 맨 첫 부분에 선언된 이 FilledTonalButton은 LazyColumn의 맨 아랫 부분에 존재하게 될 것이다.
또 DayMeal 레코드 하나하나가 Card에 담겨있기 때문에 통일성을 위해서, FilledTonalButton의 shape 프로퍼티에 CardDefaults.shape를 대입했다. 즉, FilledTonalButton은 카드 모양이 될 것이다.
#3-2 클릭 시 동작 정의
...
@Composable
fun NutrientScreen(
...
) {
...
/* ↓↓↓ viewModel.onEvent(...) 부분을 복사ㆍ붙여넣기 후 LaunchedEffect 삭제
LaunchedEffect(key1 = true) {
repeat(5) {
viewModel.onEvent(
NutrientViewModelEvent.InsertMeal(
meal = Meal(
time = LocalTime.now(),
name = "test",
nutritionInfo = NutritionInfo()
),
date = LocalDate.now()
)
)
}
}
*/
...
LazyColumn(
...
) {
item {
FilledTonalButton(
onClick = {
viewModel.onEvent(
NutrientViewModelEvent.InsertMeal(
meal = Meal(
time = LocalTime.now(),
name = "test",
nutritionInfo = NutritionInfo()
),
date = LocalDate.now()
)
)
},
...
) {
...
}
}
...
itemsIndexed(...) { ... ->
...
}
}
}
onClick = { ... } 안에 'NutrientScreen 실행 시 마다 레코드를 5개씩 INSERT시켰던 LaunchedEffect'의 INSERT 이벤트를 복사ㆍ붙여넣기 한다. 'NutrientScreen 실행 시 마다 레코드를 5개씩 INSERT시켰던 LaunchedEffect'는 이제 필요가 없으므로 삭제한다.
#4 코드 - DELETE 버튼
#4-1 모양 잡기
...
@Composable
fun NutrientScreen(
...
) {
...
LazyColumn(
...
) {
item {
...
}
...
itemsIndexed(dayMeals) { index, dayMeal ->
Card(
...
) {
Box(
modifier = Modifier.fillMaxSize()
) {
Column(
...
) {
...
}
IconButton(
onClick = {
// TODO
},
modifier = Modifier.align(Alignment.TopStart)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Delete",
modifier = Modifier.size(24.dp)
)
}
}
}
}
}
}
Column을 Box에 넣고, IconButton를 Box의 TopStart 부분에 추가한다.
#4-2 클릭 시 동작 정의
...
@Composable
fun NutrientScreen(
...
) {
...
LazyColumn(
...
) {
item {
...
}
...
itemsIndexed(dayMeals) { index, dayMeal ->
Card(
...
) {
Box(
modifier = Modifier.fillMaxSize()
) {
Column(
...
) {
...
}
IconButton(
onClick = {
viewModel.onEvent(
NutrientViewModelEvent.DeleteDayMeal(
dayMeal = dayMeal
)
)
},
modifier = Modifier.align(Alignment.TopStart)
) {
Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Delete",
modifier = Modifier.size(24.dp)
)
}
}
}
}
}
}
이전 게시글에서 만들었던 DeleteDayMeal() 이벤트를 사용한다.
#5 완성된 앱
#5-1 스크린샷
#5-2 이 게시글 시점의 Commit
#5-3 본 프로젝트의 가장 최신 Commit
'App 개발 일지 > Nutri Capture' 카테고리의 다른 글
Nutri Capture 백엔드 - 이진 탐색 적용 (1) | 2024.12.17 |
---|---|
Nutri Capture 프론트엔드 - item 추가ㆍ제거 애니메이션 (0) | 2024.12.15 |
Nutri Capture 백엔드 - DeleteDayMeal 이벤트 추가 (0) | 2024.11.28 |
Nutri Capture 백엔드 - DAO 논리적 오류 수정 (0) | 2024.11.26 |
Nutri Capture 프론트엔드 - 무한 스크롤 로직 리팩토링 (0) | 2024.11.16 |