Skip to content

Commit 55e0863

Browse files
committed
FEAT: 감정구슬 리디자인 화면 세부 조정 및 감정 구슬 데이터에 배경/텍스트 색상 변수 추가
1 parent ef69c1d commit 55e0863

4 files changed

Lines changed: 166 additions & 73 deletions

File tree

presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/EmotionScreen.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import androidx.compose.runtime.getValue
77
import androidx.hilt.navigation.compose.hiltViewModel
88
import com.threegap.bitnagil.presentation.common.flow.collectAsEffect
99
import com.threegap.bitnagil.presentation.emotion.component.template.EmotionRecommendRoutineScreen
10-
import com.threegap.bitnagil.presentation.emotion.component.template.SimpleEmotionSelectionScreen
10+
import com.threegap.bitnagil.presentation.emotion.component.template.SwipeEmotionSelectionScreen
1111
import com.threegap.bitnagil.presentation.emotion.model.EmotionScreenStep
1212
import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionSideEffect
1313

@@ -29,10 +29,10 @@ fun EmotionScreenContainer(
2929
}
3030

3131
when (state.step) {
32-
EmotionScreenStep.Emotion -> SimpleEmotionSelectionScreen(
32+
EmotionScreenStep.Emotion -> SwipeEmotionSelectionScreen(
3333
state = state,
3434
onClickPreviousButton = navigateToBack,
35-
onClickEmotion = viewModel::selectEmotion,
35+
onSelectEmotion = viewModel::selectEmotion,
3636
)
3737
EmotionScreenStep.RecommendRoutines -> EmotionRecommendRoutineScreen(
3838
state = state,

presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/component/atom/EmotionMarbleImage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ fun EmotionMarbleImage(
1515
modifier: Modifier,
1616
image: EmotionImageUiModel,
1717
contentDescription: String? = null,
18+
alpha: Float = 1f,
1819
) {
1920
when (image) {
2021
is EmotionImageUiModel.Url -> {
@@ -25,6 +26,7 @@ fun EmotionMarbleImage(
2526
.build(),
2627
modifier = modifier,
2728
contentDescription = null,
29+
alpha = alpha,
2830
error = image.offlineBackupImageResourceId?.let { painterResource(it) },
2931
)
3032
}

presentation/src/main/java/com/threegap/bitnagil/presentation/emotion/component/template/SwipeEmotionSelectionScreen.kt

Lines changed: 116 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.threegap.bitnagil.presentation.emotion.component.template
22

33
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.EnterTransition
5+
import androidx.compose.animation.ExitTransition
46
import androidx.compose.animation.core.Animatable
57
import androidx.compose.animation.core.tween
68
import androidx.compose.animation.fadeIn
@@ -67,14 +69,35 @@ import com.threegap.bitnagil.presentation.emotion.model.mvi.EmotionState
6769
import kotlinx.coroutines.delay
6870
import kotlinx.coroutines.launch
6971
import kotlin.math.absoluteValue
70-
import kotlin.math.max
7172

7273
@Composable
7374
fun SwipeEmotionSelectionScreen(
7475
state: EmotionState,
7576
onClickPreviousButton: () -> Unit,
7677
onSelectEmotion: (String) -> Unit,
7778
) {
79+
val fadeInTransition = remember { fadeIn(animationSpec = tween(150)) }
80+
val fadeOutTransition = remember { fadeOut(animationSpec = tween(50)) }
81+
82+
val emotions = remember(state.emotionTypeUiModels) { state.emotionTypeUiModels + EmotionUiModel.Default }
83+
val actualItemCount = emotions.size
84+
85+
val pagerState = rememberPagerState(
86+
initialPage = Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2 % actualItemCount),
87+
pageCount = { Int.MAX_VALUE },
88+
)
89+
var showText by remember { mutableStateOf(true) }
90+
val currentItem = emotions[pagerState.currentPage % actualItemCount]
91+
92+
LaunchedEffect(pagerState.isScrollInProgress) {
93+
if (pagerState.isScrollInProgress) {
94+
showText = false
95+
} else {
96+
delay(250)
97+
showText = true
98+
}
99+
}
100+
78101
Column(
79102
modifier = Modifier
80103
.fillMaxSize()
@@ -99,47 +122,21 @@ fun SwipeEmotionSelectionScreen(
99122
) {
100123
state.emotionTypeUiModels.forEach { emotion ->
101124
EmotionMarbleImage(
102-
modifier = Modifier
103-
.size(40.dp)
104-
.background(color = BitnagilTheme.colors.coolGray98),
125+
modifier = Modifier.size(40.dp),
105126
image = emotion.image,
127+
alpha = if (emotion.emotionType == currentItem.emotionType) 1f else 0.3f
106128
)
107129
}
108130
}
109131

110132
Spacer(modifier = Modifier.height(26.dp))
111133

112-
Column(
113-
horizontalAlignment = Alignment.CenterHorizontally,
114-
) {
115-
Box(
116-
modifier = Modifier
117-
.background(Color(0xFFEFECFF), shape = RoundedCornerShape(12.dp))
118-
.padding(20.dp),
119-
contentAlignment = Alignment.Center,
120-
) {
121-
Text(
122-
"평온함은 마음이 고요하고 편안해\n균형을 이루는 상태에요",
123-
style = BitnagilTheme.typography.cafe24SsurroundAir2.copy(color = Color(0xFF692BD0)),
124-
textAlign = TextAlign.Center,
125-
)
126-
}
127-
128-
Canvas(
129-
modifier = Modifier
130-
.height(10.dp)
131-
.width(24.dp),
132-
) {
133-
val path = Path().apply {
134-
moveTo(0f, 0f)
135-
lineTo(size.width, 0f)
136-
lineTo(size.width / 2 , size.height)
137-
lineTo(0f, 0f)
138-
close()
139-
}
140-
drawPath(path, color = Color(0xFFEFECFF))
141-
}
142-
}
134+
EmotionDescriptionText(
135+
emotion = currentItem,
136+
showText = showText,
137+
enterTransition = fadeInTransition,
138+
exitTransition = fadeOutTransition
139+
)
143140

144141
Spacer(modifier = Modifier.height(16.dp))
145142

@@ -149,18 +146,23 @@ fun SwipeEmotionSelectionScreen(
149146
EmotionPager(
150147
modifier = Modifier
151148
.fillMaxSize()
149+
.padding(bottom = 90.dp)
152150
.zIndex(1f),
153-
emotions = state.emotionTypeUiModels,
151+
emotions = emotions,
154152
enabled = !state.isLoading,
155153
onSelectEmotion = onSelectEmotion,
154+
pagerState = pagerState,
155+
showText = showText,
156+
marbleNameTextEnterTransition = fadeInTransition,
157+
marbleNameTextExitTransition = fadeOutTransition,
156158
)
157159

158160
Column(
159161
modifier = Modifier.align(Alignment.BottomCenter),
160162
horizontalAlignment = Alignment.CenterHorizontally,
161163
) {
162164
GestureDescriptionText(
163-
currentEmotionSelectable = state.emotionTypeUiModels.any { it.selectable },
165+
currentEmotionSelectable = currentItem.selectable,
164166
)
165167

166168
Spacer(modifier = Modifier.height(12.dp))
@@ -187,6 +189,58 @@ fun SwipeEmotionSelectionScreen(
187189
}
188190
}
189191

192+
@Composable
193+
private fun EmotionDescriptionText(
194+
emotion: EmotionUiModel,
195+
showText: Boolean,
196+
enterTransition: EnterTransition,
197+
exitTransition: ExitTransition,
198+
) {
199+
Box(
200+
modifier = Modifier.height(102.dp)
201+
) {
202+
AnimatedVisibility(
203+
visible = emotion.message != null && showText,
204+
enter = enterTransition,
205+
exit = exitTransition,
206+
) {
207+
Column(
208+
horizontalAlignment = Alignment.CenterHorizontally,
209+
) {
210+
Box(
211+
modifier = Modifier
212+
.background(Color(emotion.symbolBackgroundColor), shape = RoundedCornerShape(12.dp))
213+
.padding(20.dp),
214+
contentAlignment = Alignment.Center,
215+
) {
216+
Text(
217+
text = emotion.message ?: "",
218+
style = BitnagilTheme.typography.cafe24SsurroundAir2.copy(color = Color(emotion.symbolColor)),
219+
textAlign = TextAlign.Center,
220+
maxLines = 2,
221+
minLines = 2,
222+
)
223+
}
224+
225+
Canvas(
226+
modifier = Modifier
227+
.height(10.dp)
228+
.width(24.dp),
229+
) {
230+
val path = Path().apply {
231+
moveTo(0f, 0f)
232+
lineTo(size.width, 0f)
233+
lineTo(size.width / 2, size.height)
234+
lineTo(0f, 0f)
235+
close()
236+
}
237+
drawPath(path, color = Color(emotion.symbolBackgroundColor))
238+
}
239+
}
240+
}
241+
}
242+
}
243+
190244
@Composable
191245
private fun GestureDescriptionText(
192246
currentEmotionSelectable: Boolean,
@@ -237,25 +291,12 @@ private fun EmotionPager(
237291
emotions: List<EmotionUiModel>,
238292
enabled: Boolean,
239293
onSelectEmotion: (String) -> Unit,
294+
pagerState: PagerState,
295+
showText: Boolean,
296+
marbleNameTextEnterTransition: EnterTransition,
297+
marbleNameTextExitTransition: ExitTransition,
240298
) {
241-
val actualItemCount = max(1, emotions.size)
242-
243-
val pagerState = rememberPagerState(
244-
initialPage = Int.MAX_VALUE / 2 - (Int.MAX_VALUE / 2 % actualItemCount),
245-
pageCount = { Int.MAX_VALUE },
246-
)
247-
248-
var showText by remember { mutableStateOf(true) }
249-
val currentItem = emotions[pagerState.currentPage % actualItemCount]
250-
251-
LaunchedEffect(pagerState.isScrollInProgress) {
252-
if (pagerState.isScrollInProgress) {
253-
showText = false
254-
} else {
255-
delay(500)
256-
showText = true
257-
}
258-
}
299+
val currentItem = emotions[pagerState.currentPage % emotions.size]
259300

260301
BoxWithConstraints(
261302
modifier = modifier,
@@ -264,9 +305,10 @@ private fun EmotionPager(
264305
val density = LocalDensity.current
265306
val screenWidth = with(density) { constraints.maxWidth.toDp() }
266307

267-
val itemWidth = 140.dp
268-
val contentPadding = (screenWidth - itemWidth) / 2
269-
val pageSpacing = ((screenWidth - itemWidth * 2) / 2)
308+
val itemSize = 140.dp
309+
val centerItemYOffset = 50.dp
310+
val contentPadding = (screenWidth - itemSize) / 2
311+
val pageSpacing = ((screenWidth - itemSize * 2) / 2)
270312

271313
HorizontalPager(
272314
modifier = Modifier.fillMaxHeight(),
@@ -275,32 +317,33 @@ private fun EmotionPager(
275317
contentPadding = PaddingValues(horizontal = contentPadding),
276318
verticalAlignment = Alignment.Top,
277319
) { page ->
278-
val itemIndex = page % actualItemCount
320+
val itemIndex = page % emotions.size
279321
EmotionPagerItem(
280322
emotion = emotions[itemIndex],
281323
pagerState = pagerState,
282324
page = page,
283-
size = itemWidth,
284-
maximumDraggableYOffset = constraints.maxHeight - 280.dp.dpToPx(),
285-
enabled = enabled,
325+
size = itemSize,
326+
centerItemYOffset = centerItemYOffset.dpToPx(),
327+
maximumDraggableYOffset = constraints.maxHeight - (itemSize + centerItemYOffset).dpToPx(),
328+
enabled = enabled && emotions[itemIndex].selectable,
286329
onSelectEmotion = onSelectEmotion,
287330
)
288331
}
289332

290333
AnimatedVisibility(
291334
visible = showText,
292-
enter = fadeIn(animationSpec = tween(150)),
293-
exit = fadeOut(animationSpec = tween(50)),
335+
enter = marbleNameTextEnterTransition,
336+
exit = marbleNameTextExitTransition,
294337
) {
295338
Box(
296339
modifier = Modifier
297-
.background(Color(0x99E1D5FA), shape = RoundedCornerShape(10.dp))
340+
.background(Color(currentItem.symbolBackgroundColor), shape = RoundedCornerShape(10.dp))
298341
.padding(horizontal = 16.dp, vertical = 8.dp),
299342
) {
300343
Text(
301344
text = currentItem.emotionMarbleName,
302345
style = BitnagilTheme.typography.title3SemiBold,
303-
color = Color(0xFF692BD0),
346+
color = Color(currentItem.symbolColor),
304347
)
305348
}
306349
}
@@ -313,6 +356,7 @@ private fun EmotionPagerItem(
313356
pagerState: PagerState,
314357
page: Int,
315358
size: Dp,
359+
centerItemYOffset: Float,
316360
maximumDraggableYOffset: Float = Float.MAX_VALUE,
317361
enabled: Boolean,
318362
onSelectEmotion: (String) -> Unit,
@@ -330,7 +374,7 @@ private fun EmotionPagerItem(
330374
.size(size)
331375
.aspectRatio(1f)
332376
.graphicsLayer {
333-
translationY = lerp(size.value * 1f, 0f, pageOffset)
377+
translationY = lerp(start = centerItemYOffset * 1f, stop = 0f, pageOffset)
334378
}
335379
.offset {
336380
IntOffset(0, offsetY.value.toInt())
@@ -361,8 +405,7 @@ private fun EmotionPagerItem(
361405
)
362406
}
363407
},
364-
)
365-
.background(color = BitnagilTheme.colors.coolGray98),
408+
),
366409
)
367410
}
368411

@@ -380,6 +423,8 @@ private fun Preview() {
380423
url = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png",
381424
offlineBackupImageResourceId = null,
382425
),
426+
symbolBackgroundColor = 0xFFEFECFF,
427+
symbolColor = 0xFF692BD0,
383428
),
384429
EmotionUiModel(
385430
emotionType = "emotionType",
@@ -388,8 +433,9 @@ private fun Preview() {
388433
url = "https://bitnagil-s3.s3.ap-northeast-2.amazonaws.com/home_satisfaction.png",
389434
offlineBackupImageResourceId = null,
390435
),
436+
symbolBackgroundColor = 0xFFE9FAD0,
437+
symbolColor = 0xFF609F00,
391438
),
392-
EmotionUiModel.Default
393439
),
394440
isLoading = false,
395441
step = EmotionScreenStep.Emotion,

0 commit comments

Comments
 (0)