Skip to content

Commit 297d837

Browse files
authored
Merge pull request #181 from YAPP-Github/refactor/#168-home-nestedscroll
[Refactor/#168] 홈화면 NestedScroll 로직을 개선합니다.
2 parents 057eeb4 + 172764b commit 297d837

File tree

6 files changed

+298
-342
lines changed

6 files changed

+298
-342
lines changed

presentation/src/main/java/com/threegap/bitnagil/presentation/home/HomeScreen.kt

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,44 @@ import androidx.compose.foundation.background
44
import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Box
66
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.PaddingValues
78
import androidx.compose.foundation.layout.Row
8-
import androidx.compose.foundation.layout.Spacer
99
import androidx.compose.foundation.layout.fillMaxSize
1010
import androidx.compose.foundation.layout.fillMaxWidth
1111
import androidx.compose.foundation.layout.height
1212
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.foundation.layout.statusBarsPadding
1314
import androidx.compose.foundation.lazy.LazyColumn
1415
import androidx.compose.foundation.lazy.items
16+
import androidx.compose.foundation.rememberScrollState
1517
import androidx.compose.foundation.shape.RoundedCornerShape
18+
import androidx.compose.foundation.verticalScroll
1619
import androidx.compose.material3.Text
1720
import androidx.compose.runtime.Composable
1821
import androidx.compose.runtime.getValue
1922
import androidx.compose.ui.Alignment
2023
import androidx.compose.ui.Modifier
24+
import androidx.compose.ui.draw.clip
25+
import androidx.compose.ui.graphics.graphicsLayer
2126
import androidx.compose.ui.input.nestedscroll.nestedScroll
2227
import androidx.compose.ui.tooling.preview.Preview
2328
import androidx.compose.ui.unit.dp
2429
import androidx.hilt.navigation.compose.hiltViewModel
2530
import com.threegap.bitnagil.designsystem.BitnagilTheme
2631
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple
27-
import com.threegap.bitnagil.presentation.home.component.template.CollapsibleHomeHeader
32+
import com.threegap.bitnagil.presentation.home.component.template.CollapsibleHeader
2833
import com.threegap.bitnagil.presentation.home.component.template.EmptyRoutineView
2934
import com.threegap.bitnagil.presentation.home.component.template.RoutineSection
35+
import com.threegap.bitnagil.presentation.home.component.template.StickyHeader
3036
import com.threegap.bitnagil.presentation.home.component.template.WeeklyDatePicker
3137
import com.threegap.bitnagil.presentation.home.contract.HomeSideEffect
3238
import com.threegap.bitnagil.presentation.home.contract.HomeState
33-
import com.threegap.bitnagil.presentation.home.util.rememberCollapsibleHeaderState
39+
import com.threegap.bitnagil.presentation.home.model.DailyEmotionUiModel
40+
import com.threegap.bitnagil.presentation.home.model.rememberCollapsibleHeaderState
3441
import org.orbitmvi.orbit.compose.collectAsState
3542
import org.orbitmvi.orbit.compose.collectSideEffect
3643
import java.time.LocalDate
44+
import kotlin.math.pow
3745

3846
@Composable
3947
fun HomeScreenContainer(
@@ -71,6 +79,7 @@ fun HomeScreenContainer(
7179
@Composable
7280
private fun HomeScreen(
7381
uiState: HomeState,
82+
modifier: Modifier = Modifier,
7483
onDateSelect: (LocalDate) -> Unit,
7584
onPreviousWeekClick: () -> Unit,
7685
onNextWeekClick: () -> Unit,
@@ -80,48 +89,63 @@ private fun HomeScreen(
8089
onRegisterRoutineClick: () -> Unit,
8190
onRegisterEmotionClick: () -> Unit,
8291
onShowMoreRoutinesClick: () -> Unit,
83-
modifier: Modifier = Modifier,
8492
) {
8593
val collapsibleHeaderState = rememberCollapsibleHeaderState()
8694

8795
Box(
8896
modifier = modifier
8997
.fillMaxSize()
90-
.background(BitnagilTheme.colors.coolGray10),
98+
.background(BitnagilTheme.colors.coolGray10)
99+
.statusBarsPadding()
100+
.nestedScroll(collapsibleHeaderState.nestedScrollConnection),
91101
) {
92-
Column {
93-
Spacer(modifier = Modifier.height(collapsibleHeaderState.currentHeaderHeight))
102+
StickyHeader(
103+
modifier = Modifier
104+
.padding(top = 14.dp)
105+
.height(collapsibleHeaderState.stickyHeaderHeightDp),
106+
onHelpClick = onHelpClick,
107+
)
108+
109+
CollapsibleHeader(
110+
modifier = Modifier
111+
.fillMaxWidth()
112+
.padding(top = 80.dp, start = 18.dp, end = 18.dp)
113+
.height(collapsibleHeaderState.expandedHeaderHeightDp)
114+
.graphicsLayer { alpha = collapsibleHeaderState.expansionProgress.pow(3) },
115+
welcomeMessage = "${uiState.userNickname}${uiState.dailyEmotion.homeMessage}",
116+
dailyEmotion = uiState.dailyEmotion,
117+
onRegisterEmotionClick = onRegisterEmotionClick,
118+
)
94119

120+
Column(
121+
modifier = Modifier
122+
.fillMaxSize()
123+
.padding(top = collapsibleHeaderState.collapsedContentOffsetDp)
124+
.graphicsLayer { translationY = collapsibleHeaderState.currentHeightPx }
125+
.clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp))
126+
.background(color = BitnagilTheme.colors.coolGray99),
127+
) {
95128
WeeklyDatePicker(
96129
selectedDate = uiState.selectedDate,
97130
weeklyDates = uiState.currentWeeks,
98131
routines = uiState.routineSchedule,
99132
onDateSelect = onDateSelect,
100133
onPreviousWeekClick = onPreviousWeekClick,
101134
onNextWeekClick = onNextWeekClick,
102-
modifier = Modifier
103-
.background(
104-
color = BitnagilTheme.colors.coolGray99,
105-
shape = RoundedCornerShape(
106-
topStart = 20.dp,
107-
topEnd = 20.dp,
108-
),
109-
),
110135
)
111136

112137
if (uiState.selectedDateRoutines.isEmpty()) {
113138
EmptyRoutineView(
114-
onRegisterRoutineClick = onRegisterRoutineClick,
115139
modifier = Modifier
116140
.fillMaxSize()
117-
.background(BitnagilTheme.colors.coolGray99)
118-
.padding(top = 62.dp),
141+
.padding(top = 62.dp)
142+
.verticalScroll(rememberScrollState()),
143+
onRegisterRoutineClick = onRegisterRoutineClick,
119144
)
120145
} else {
121146
Row(
122147
modifier = Modifier
123148
.fillMaxWidth()
124-
.background(BitnagilTheme.colors.coolGray99)
125149
.padding(start = 16.dp, end = 4.dp),
126150
horizontalArrangement = Arrangement.SpaceBetween,
127151
verticalAlignment = Alignment.Top,
@@ -145,15 +169,13 @@ private fun HomeScreen(
145169
LazyColumn(
146170
modifier = Modifier
147171
.fillMaxSize()
148-
.background(BitnagilTheme.colors.coolGray99)
149-
.nestedScroll(collapsibleHeaderState.nestedScrollConnection)
150172
.padding(horizontal = 16.dp),
151-
state = collapsibleHeaderState.lazyListState,
152173
verticalArrangement = Arrangement.spacedBy(12.dp),
174+
contentPadding = PaddingValues(bottom = 48.dp),
153175
) {
154176
items(
155177
items = uiState.selectedDateRoutines,
156-
key = { routine -> "${routine.id}_${uiState.selectedDate}" },
178+
key = { routine -> routine.id },
157179
) { routine ->
158180
RoutineSection(
159181
routine = routine,
@@ -166,22 +188,19 @@ private fun HomeScreen(
166188
}
167189
}
168190
}
169-
170-
CollapsibleHomeHeader(
171-
userName = uiState.userNickname,
172-
dailyEmotion = uiState.dailyEmotion,
173-
collapsibleHeaderState = collapsibleHeaderState,
174-
onHelpClick = onHelpClick,
175-
onRegisterEmotion = onRegisterEmotionClick,
176-
)
177191
}
178192
}
179193

180194
@Preview
181195
@Composable
182196
private fun HomeScreenPreview() {
183197
HomeScreen(
184-
uiState = HomeState.INIT,
198+
uiState = HomeState.INIT.copy(
199+
userNickname = "홍길동",
200+
dailyEmotion = DailyEmotionUiModel.INIT.copy(
201+
homeMessage = "님, 오셨군요!\n오늘 기분은 어떤가요?",
202+
),
203+
),
185204
onDateSelect = {},
186205
onPreviousWeekClick = {},
187206
onNextWeekClick = {},
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.threegap.bitnagil.presentation.home.component.template
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Box
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.fillMaxWidth
7+
import androidx.compose.foundation.layout.size
8+
import androidx.compose.material3.Text
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.Alignment
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.res.painterResource
13+
import androidx.compose.ui.text.font.FontWeight
14+
import androidx.compose.ui.text.style.LineHeightStyle
15+
import androidx.compose.ui.tooling.preview.Preview
16+
import androidx.compose.ui.unit.dp
17+
import coil3.compose.AsyncImage
18+
import com.threegap.bitnagil.designsystem.BitnagilTheme
19+
import com.threegap.bitnagil.designsystem.R
20+
import com.threegap.bitnagil.presentation.home.component.atom.EmotionRegisterButton
21+
import com.threegap.bitnagil.presentation.home.model.DailyEmotionUiModel
22+
23+
@Composable
24+
fun CollapsibleHeader(
25+
modifier: Modifier = Modifier,
26+
welcomeMessage: String,
27+
dailyEmotion: DailyEmotionUiModel,
28+
onRegisterEmotionClick: () -> Unit,
29+
) {
30+
val baseImageHeight = 148.dp
31+
val baseImageWidth = 108.dp
32+
33+
Box(modifier = modifier) {
34+
Column(
35+
modifier = Modifier.align(Alignment.TopStart),
36+
verticalArrangement = Arrangement.spacedBy(16.dp),
37+
) {
38+
Text(
39+
text = welcomeMessage,
40+
style = BitnagilTheme.typography.cafe24SsurroundAir.copy(
41+
lineHeightStyle = LineHeightStyle(
42+
alignment = LineHeightStyle.Alignment.Center,
43+
trim = LineHeightStyle.Trim.None,
44+
),
45+
),
46+
color = BitnagilTheme.colors.white,
47+
fontWeight = FontWeight.SemiBold,
48+
)
49+
50+
EmotionRegisterButton(
51+
onClick = onRegisterEmotionClick,
52+
enabled = !dailyEmotion.hasEmotion,
53+
)
54+
}
55+
56+
AsyncImage(
57+
model = dailyEmotion.imageUrl,
58+
modifier = Modifier
59+
.align(Alignment.TopEnd)
60+
.size(baseImageWidth, baseImageHeight),
61+
contentDescription = null,
62+
placeholder = painterResource(R.drawable.default_emotion),
63+
error = painterResource(R.drawable.default_emotion),
64+
)
65+
}
66+
}
67+
68+
@Preview
69+
@Composable
70+
private fun CollapsibleHeaderPreview() {
71+
CollapsibleHeader(
72+
modifier = Modifier.fillMaxWidth(),
73+
welcomeMessage = "대현님 오셨군요!\n오늘 기분은 어떤가요?!",
74+
dailyEmotion = DailyEmotionUiModel.INIT,
75+
onRegisterEmotionClick = {},
76+
)
77+
}

0 commit comments

Comments
 (0)