Skip to content

Commit 9d266a9

Browse files
authored
Merge pull request #204 from YAPP-Github/fix/#203-collapsible-header
[Fix/#203] 홈 화면 Collapsible Header 플링 시 하단 검정 배경 노출문제 해결
2 parents f5574cc + 89edf7d commit 9d266a9

File tree

2 files changed

+26
-30
lines changed

2 files changed

+26
-30
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import androidx.compose.ui.Modifier
2424
import androidx.compose.ui.draw.clip
2525
import androidx.compose.ui.graphics.graphicsLayer
2626
import androidx.compose.ui.input.nestedscroll.nestedScroll
27+
import androidx.compose.ui.layout.boundsInParent
28+
import androidx.compose.ui.layout.onGloballyPositioned
2729
import androidx.compose.ui.tooling.preview.Preview
2830
import androidx.compose.ui.unit.dp
2931
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
@@ -102,7 +104,11 @@ private fun HomeScreen(
102104
StickyHeader(
103105
modifier = Modifier
104106
.padding(top = 14.dp)
105-
.height(collapsibleHeaderState.stickyHeaderHeightDp),
107+
.height(collapsibleHeaderState.initialStickyHeaderHeightDp)
108+
.onGloballyPositioned { coordinates ->
109+
collapsibleHeaderState.stickyHeaderActualBottomPx =
110+
coordinates.boundsInParent().bottom
111+
},
106112
onHelpClick = onHelpClick,
107113
)
108114

presentation/src/main/java/com/threegap/bitnagil/presentation/screen/home/model/CollapsibleHeaderState.kt

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,23 @@ import androidx.compose.ui.unit.dp
2323
@Stable
2424
internal class CollapsibleHeaderState(
2525
private val density: Density,
26-
val stickyHeaderHeightDp: Dp,
26+
val initialStickyHeaderHeightDp: Dp,
2727
val expandedHeaderHeightDp: Dp,
2828
) {
29-
private val stickyHeaderHeightPx: Float = with(density) { stickyHeaderHeightDp.toPx() }
30-
3129
private val expandedHeaderHeightPx: Float = with(density) { expandedHeaderHeightDp.toPx() }
30+
private val initialStickyHeaderHeightPx: Float = with(density) { initialStickyHeaderHeightDp.toPx() }
31+
32+
var stickyHeaderActualBottomPx by mutableFloatStateOf(initialStickyHeaderHeightPx)
33+
internal set
3234

33-
val collapsedContentOffsetDp: Dp = with(density) { stickyHeaderHeightPx.toDp() + 18.dp }
35+
val collapsedContentOffsetDp: Dp
36+
get() = with(density) { stickyHeaderActualBottomPx.toDp() }
3437

3538
var currentHeightPx by mutableFloatStateOf(expandedHeaderHeightPx)
3639
private set
3740

3841
val expansionProgress: Float
39-
get() = if (expandedHeaderHeightPx > 0f) (currentHeightPx / expandedHeaderHeightPx).coerceIn(0f, 1f) else 1f
42+
get() = (currentHeightPx / expandedHeaderHeightPx).coerceIn(0f, 1f)
4043

4144
val nestedScrollConnection = object : NestedScrollConnection {
4245
override fun onPreScroll(available: Offset, source: NestedScrollSource) =
@@ -46,33 +49,22 @@ internal class CollapsibleHeaderState(
4649
if (available.y > 0) consumeDelta(available.y) else Offset.Zero
4750

4851
override suspend fun onPreFling(available: Velocity): Velocity {
49-
if (currentHeightPx <= 0f || currentHeightPx >= expandedHeaderHeightPx) return Velocity.Zero
52+
val isFullyCollapsed = currentHeightPx < 1f
53+
val isFullyExpanded = currentHeightPx > expandedHeaderHeightPx - 1f
5054

51-
val collapse = 0f
52-
val expand = expandedHeaderHeightPx
55+
if (isFullyCollapsed || isFullyExpanded) return Velocity.Zero
5356

5457
val target = when {
55-
available.y < -50f -> collapse
56-
available.y > 50f -> expand
57-
else -> if (currentHeightPx - collapse < expand - currentHeightPx) collapse else expand
58+
available.y < -50f -> 0f
59+
available.y > 50f -> expandedHeaderHeightPx
60+
else -> if (currentHeightPx < expandedHeaderHeightPx / 2) 0f else expandedHeaderHeightPx
5861
}
5962

6063
snapTo(targetHeight = target, velocity = available.y)
61-
62-
return Velocity(0f, available.y)
64+
return Velocity.Zero
6365
}
6466

6567
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
66-
if (available.y > 0 && currentHeightPx < expandedHeaderHeightPx) {
67-
snapTo(targetHeight = expandedHeaderHeightPx, velocity = available.y)
68-
return Velocity(0f, available.y)
69-
}
70-
71-
if (available.y < 0 && currentHeightPx > 0f) {
72-
snapTo(targetHeight = 0f, velocity = available.y)
73-
return Velocity(0f, available.y)
74-
}
75-
7668
return Velocity.Zero
7769
}
7870
}
@@ -94,27 +86,25 @@ internal class CollapsibleHeaderState(
9486
dampingRatio = Spring.DampingRatioNoBouncy,
9587
stiffness = Spring.StiffnessMediumLow,
9688
),
97-
) { value, _ ->
98-
currentHeightPx = value
99-
}
89+
) { value, _ -> currentHeightPx = value.coerceIn(0f, expandedHeaderHeightPx) }
10090
}
10191
}
10292

10393
@Composable
10494
internal fun rememberCollapsibleHeaderState(
10595
density: Density = LocalDensity.current,
10696
windowInfo: WindowInfo = LocalWindowInfo.current,
107-
stickyHeaderHeight: Dp = 48.dp,
97+
initialStickyHeaderHeightDp: Dp = 48.dp,
10898
minExpandedHeaderHeight: Dp = 146.dp,
10999
): CollapsibleHeaderState {
110100
val containerSize = windowInfo.containerSize
111-
return remember(density, containerSize, minExpandedHeaderHeight, stickyHeaderHeight) {
101+
return remember(density, containerSize, minExpandedHeaderHeight, initialStickyHeaderHeightDp) {
112102
val screenHeightDp = with(density) { containerSize.height.toDp() }
113103
val expandedHeaderHeightDp = (screenHeightDp * 0.18f).coerceAtLeast(minExpandedHeaderHeight)
114104

115105
CollapsibleHeaderState(
116106
density = density,
117-
stickyHeaderHeightDp = stickyHeaderHeight,
107+
initialStickyHeaderHeightDp = initialStickyHeaderHeightDp,
118108
expandedHeaderHeightDp = expandedHeaderHeightDp,
119109
)
120110
}

0 commit comments

Comments
 (0)