-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPinnedTabsScaffold.kt
More file actions
88 lines (78 loc) · 3.07 KB
/
Copy pathPinnedTabsScaffold.kt
File metadata and controls
88 lines (78 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package to.bitkit.ui.scaffold
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import dev.chrisbanes.haze.HazeStyle
import dev.chrisbanes.haze.HazeTint
import dev.chrisbanes.haze.hazeEffect
import dev.chrisbanes.haze.hazeSource
import dev.chrisbanes.haze.rememberHazeState
import to.bitkit.ui.theme.Colors
private val PinnedTabsShadowHeight = 32.dp
private val PinnedTabsBlurRadius = 24.dp
private enum class PinnedTabsSlot { Header, Content, Shadow }
@Composable
fun PinnedTabsScaffold(
header: @Composable ColumnScope.() -> Unit,
modifier: Modifier = Modifier,
content: @Composable (topPadding: Dp) -> Unit,
) {
val hazeState = rememberHazeState()
val shadowBrush = remember {
Brush.verticalGradient(colors = listOf(Colors.Black, Color.Transparent))
}
val hazeStyle = remember {
HazeStyle(
backgroundColor = Colors.Black,
tint = HazeTint(Colors.Black70),
blurRadius = PinnedTabsBlurRadius,
)
}
SubcomposeLayout(modifier = modifier.fillMaxSize()) { constraints ->
val looseConstraints = constraints.copy(minWidth = 0, minHeight = 0)
val headerPlaceables = subcompose(PinnedTabsSlot.Header) {
Column(
modifier = Modifier
.fillMaxWidth()
.hazeEffect(state = hazeState, style = hazeStyle),
content = { header() },
)
}.map { it.measure(looseConstraints) }
val headerHeightPx = headerPlaceables.maxOfOrNull { it.height } ?: 0
val headerHeightDp = headerHeightPx.toDp()
val contentPlaceables = subcompose(PinnedTabsSlot.Content) {
Box(
modifier = Modifier
.fillMaxSize()
.hazeSource(hazeState)
) {
content(headerHeightDp)
}
}.map { it.measure(constraints) }
val shadowPlaceables = subcompose(PinnedTabsSlot.Shadow) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(PinnedTabsShadowHeight)
.background(shadowBrush)
)
}.map { it.measure(looseConstraints) }
layout(constraints.maxWidth, constraints.maxHeight) {
contentPlaceables.forEach { it.placeRelative(0, 0) }
shadowPlaceables.forEach { it.placeRelative(0, headerHeightPx) }
headerPlaceables.forEach { it.placeRelative(0, 0) }
}
}
}