@momo-kits/native-kits 0.113.2-beta.13 → 0.113.2-beta.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +29 -57
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +40 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +5 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +41 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +2 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +11 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +22 -14
- package/local.properties +2 -2
- package/package.json +1 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.animateColorAsState
|
|
4
3
|
import androidx.compose.foundation.background
|
|
5
4
|
import androidx.compose.foundation.border
|
|
6
5
|
import androidx.compose.foundation.clickable
|
|
@@ -24,7 +23,6 @@ import androidx.compose.runtime.setValue
|
|
|
24
23
|
import androidx.compose.runtime.snapshotFlow
|
|
25
24
|
import androidx.compose.ui.Alignment
|
|
26
25
|
import androidx.compose.ui.Modifier
|
|
27
|
-
import androidx.compose.ui.graphics.Color
|
|
28
26
|
import androidx.compose.ui.graphics.graphicsLayer
|
|
29
27
|
import androidx.compose.ui.semantics.semantics
|
|
30
28
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -42,15 +40,6 @@ import vn.momo.kits.const.Spacing
|
|
|
42
40
|
import vn.momo.kits.modifier.setAutomationId
|
|
43
41
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
44
42
|
|
|
45
|
-
enum class TitlePosition {
|
|
46
|
-
LEFT, CENTER,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
data class AnimatedHeader(
|
|
50
|
-
val type: HeaderType = HeaderType.DEFAULT,
|
|
51
|
-
val composable: @Composable (scrollState: Int) -> Unit = {}
|
|
52
|
-
)
|
|
53
|
-
|
|
54
43
|
@Composable
|
|
55
44
|
fun Header(
|
|
56
45
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
@@ -77,24 +66,15 @@ fun Header(
|
|
|
77
66
|
.collect { fraction -> colorFraction = fraction }
|
|
78
67
|
}
|
|
79
68
|
|
|
80
|
-
val backgroundSearch
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
colorFraction
|
|
85
|
-
)
|
|
69
|
+
val backgroundSearch = animateColor(
|
|
70
|
+
Colors.black_01,
|
|
71
|
+
AppTheme.current.colors.background.default,
|
|
72
|
+
colorFraction
|
|
86
73
|
)
|
|
87
74
|
|
|
88
|
-
val backgroundColor = if (scrollState == 0) {
|
|
89
|
-
Color.Transparent
|
|
90
|
-
} else {
|
|
91
|
-
AppTheme.current.colors.background.surface
|
|
92
|
-
}
|
|
93
|
-
|
|
94
75
|
if (headerType != HeaderType.NONE) {
|
|
95
76
|
BoxWithConstraints(
|
|
96
77
|
Modifier.height(statusBarHeight + 52.dp)
|
|
97
|
-
.background(backgroundColor)
|
|
98
78
|
.fillMaxWidth()
|
|
99
79
|
.zIndex(10f),
|
|
100
80
|
contentAlignment = Alignment.BottomCenter
|
|
@@ -138,9 +118,9 @@ fun Header(
|
|
|
138
118
|
}
|
|
139
119
|
}
|
|
140
120
|
|
|
141
|
-
if (
|
|
121
|
+
if (useAnimationSearch || inputSearchProps == null) {
|
|
142
122
|
Box(Modifier.graphicsLayer {
|
|
143
|
-
alpha = if (
|
|
123
|
+
alpha = if (animatedHeader !== null) opacity ?: 1f else 1f
|
|
144
124
|
}) {
|
|
145
125
|
headerRight?.invoke()
|
|
146
126
|
}
|
|
@@ -156,40 +136,32 @@ fun Header(
|
|
|
156
136
|
) {
|
|
157
137
|
if (goBack != null && titlePosition == TitlePosition.LEFT) {
|
|
158
138
|
Spacer(Modifier.width(40.dp))
|
|
159
|
-
}
|
|
160
|
-
if (inputSearchProps != null && !useAnimationSearch) {
|
|
161
|
-
InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
|
|
162
139
|
} else {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
140
|
+
if (inputSearchProps != null && !useAnimationSearch) {
|
|
141
|
+
InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
|
|
142
|
+
} else {
|
|
143
|
+
Box(
|
|
144
|
+
Modifier.weight(1f).graphicsLayer {
|
|
145
|
+
alpha = if (useAnimationSearch) {
|
|
146
|
+
1f - (opacity ?: 1f)
|
|
147
|
+
} else {
|
|
148
|
+
if (animatedHeader !== null) opacity ?: 1f else 1f
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
|
|
152
|
+
) {
|
|
153
|
+
|
|
154
|
+
HeaderTitle(
|
|
155
|
+
title = title,
|
|
156
|
+
color = tintIconColor,
|
|
157
|
+
modifier = Modifier.semantics {
|
|
158
|
+
testTag = "title_navigation_header"
|
|
159
|
+
}
|
|
160
|
+
)
|
|
161
|
+
}
|
|
180
162
|
}
|
|
181
163
|
}
|
|
182
164
|
}
|
|
183
165
|
}
|
|
184
166
|
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
fun animateColor(start: Color, stop: Color, fraction: Float): Color {
|
|
189
|
-
return Color(
|
|
190
|
-
red = start.red + fraction * (stop.red - start.red),
|
|
191
|
-
green = start.green + fraction * (stop.green - start.green),
|
|
192
|
-
blue = start.blue + fraction * (stop.blue - start.blue),
|
|
193
|
-
alpha = start.alpha + fraction * (stop.alpha - start.alpha)
|
|
194
|
-
)
|
|
195
|
-
}
|
|
167
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.animateColorAsState
|
|
4
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
3
5
|
import androidx.compose.foundation.layout.Box
|
|
4
6
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
5
7
|
import androidx.compose.runtime.Composable
|
|
8
|
+
import androidx.compose.runtime.getValue
|
|
6
9
|
import androidx.compose.ui.Modifier
|
|
7
10
|
import androidx.compose.ui.graphics.Color
|
|
8
11
|
import androidx.compose.ui.unit.Dp
|
|
@@ -10,11 +13,25 @@ import androidx.compose.ui.unit.dp
|
|
|
10
13
|
import vn.momo.kits.components.InputSearchProps
|
|
11
14
|
import vn.momo.kits.const.AppStatusBar
|
|
12
15
|
import vn.momo.kits.const.AppTheme
|
|
13
|
-
import vn.momo.kits.platform.getScreenDimensions
|
|
14
16
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
enum class TitlePosition {
|
|
19
|
+
LEFT, CENTER,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
data class AnimatedHeader(
|
|
23
|
+
val type: HeaderType = HeaderType.DEFAULT,
|
|
24
|
+
val composable: @Composable (scrollState: Int) -> Unit = {}
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
fun animateColor(start: Color, stop: Color, fraction: Float): Color {
|
|
28
|
+
return Color(
|
|
29
|
+
red = start.red + fraction * (stop.red - start.red),
|
|
30
|
+
green = start.green + fraction * (stop.green - start.green),
|
|
31
|
+
blue = start.blue + fraction * (stop.blue - start.blue),
|
|
32
|
+
alpha = start.alpha + fraction * (stop.alpha - start.alpha)
|
|
33
|
+
)
|
|
34
|
+
}
|
|
18
35
|
|
|
19
36
|
@Composable
|
|
20
37
|
fun HeaderBackground(
|
|
@@ -26,41 +43,39 @@ fun HeaderBackground(
|
|
|
26
43
|
useAnimationSearch: Boolean = false
|
|
27
44
|
) {
|
|
28
45
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
29
|
-
val screenWidth = getScreenDimensions().width
|
|
30
|
-
val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
|
|
31
|
-
val searchWidth = screenWidth - (SCREEN_PADDING * 2)
|
|
32
46
|
|
|
33
|
-
val
|
|
34
|
-
|
|
35
|
-
statusBarHeight = statusBarHeight,
|
|
36
|
-
leftPosition = leftPosition,
|
|
37
|
-
searchWidth = searchWidth,
|
|
38
|
-
headerRightWidth = headerRightWidth
|
|
47
|
+
val opacityAni by animateFloatAsState(
|
|
48
|
+
targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f),
|
|
39
49
|
)
|
|
40
50
|
|
|
41
|
-
val backgroundColor
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
val backgroundColor by animateColorAsState(
|
|
52
|
+
targetValue = animateColor(
|
|
53
|
+
Color.Transparent,
|
|
54
|
+
AppTheme.current.colors.background.surface,
|
|
55
|
+
opacityAni
|
|
56
|
+
),
|
|
57
|
+
)
|
|
46
58
|
|
|
47
59
|
when (headerType) {
|
|
48
60
|
HeaderType.DEFAULT -> {
|
|
49
|
-
val height = statusBarHeight + 52.dp
|
|
50
61
|
HeaderDefault(
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
backgroundColor = backgroundColor
|
|
62
|
+
opacityAni = opacityAni,
|
|
63
|
+
statusBarHeight = statusBarHeight,
|
|
64
|
+
backgroundColor = backgroundColor,
|
|
54
65
|
)
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
HeaderType.EXTENDED -> {
|
|
58
|
-
|
|
59
|
-
|
|
69
|
+
HeaderExtended(
|
|
70
|
+
scrollState = scrollState,
|
|
60
71
|
inputSearchProps = inputSearchProps,
|
|
72
|
+
headerRightWidth = headerRightWidth,
|
|
61
73
|
useAnimationSearch = useAnimationSearch,
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
opacityAni = opacityAni,
|
|
75
|
+
isBack = isBack,
|
|
76
|
+
statusBarHeight = statusBarHeight,
|
|
77
|
+
backgroundColor = backgroundColor,
|
|
78
|
+
)
|
|
64
79
|
}
|
|
65
80
|
|
|
66
81
|
else -> {
|
|
@@ -21,10 +21,11 @@ import vn.momo.kits.utils.bottomBorder
|
|
|
21
21
|
|
|
22
22
|
@Composable
|
|
23
23
|
fun HeaderDefault(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
opacityAni: Float,
|
|
25
|
+
statusBarHeight: Dp,
|
|
26
|
+
backgroundColor: Color
|
|
27
27
|
) {
|
|
28
|
+
val height = statusBarHeight + 52.dp
|
|
28
29
|
Box(
|
|
29
30
|
modifier = Modifier.fillMaxWidth().height(height)
|
|
30
31
|
.background(backgroundColor)
|
|
@@ -37,7 +38,7 @@ fun HeaderDefault(
|
|
|
37
38
|
modifier = Modifier
|
|
38
39
|
.height(height)
|
|
39
40
|
.fillMaxWidth()
|
|
40
|
-
.alpha(
|
|
41
|
+
.alpha(opacityAni)
|
|
41
42
|
.background(
|
|
42
43
|
Brush.linearGradient(
|
|
43
44
|
colors = listOf(
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.animateColorAsState
|
|
4
|
+
import androidx.compose.animation.core.animateFloatAsState
|
|
3
5
|
import androidx.compose.foundation.background
|
|
4
6
|
import androidx.compose.foundation.layout.Box
|
|
5
7
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@@ -9,6 +11,7 @@ import androidx.compose.foundation.layout.padding
|
|
|
9
11
|
import androidx.compose.foundation.layout.width
|
|
10
12
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
11
13
|
import androidx.compose.runtime.Composable
|
|
14
|
+
import androidx.compose.runtime.getValue
|
|
12
15
|
import androidx.compose.ui.Alignment
|
|
13
16
|
import androidx.compose.ui.Modifier
|
|
14
17
|
import androidx.compose.ui.draw.alpha
|
|
@@ -17,30 +20,47 @@ import androidx.compose.ui.graphics.Brush
|
|
|
17
20
|
import androidx.compose.ui.graphics.Color
|
|
18
21
|
import androidx.compose.ui.layout.ContentScale
|
|
19
22
|
import androidx.compose.ui.platform.LocalDensity
|
|
23
|
+
import androidx.compose.ui.unit.Dp
|
|
20
24
|
import androidx.compose.ui.unit.dp
|
|
21
25
|
import vn.momo.kits.components.Image
|
|
22
26
|
import vn.momo.kits.components.InputSearch
|
|
23
27
|
import vn.momo.kits.components.InputSearchProps
|
|
24
28
|
import vn.momo.kits.components.Options
|
|
25
29
|
import vn.momo.kits.const.AppTheme
|
|
30
|
+
import vn.momo.kits.const.Colors
|
|
26
31
|
import vn.momo.kits.const.Radius
|
|
27
32
|
import vn.momo.kits.const.Spacing
|
|
33
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
34
|
+
import vn.momo.kits.utils.bottomBorder
|
|
28
35
|
|
|
29
36
|
@Composable
|
|
30
37
|
fun HeaderExtended(
|
|
31
|
-
|
|
32
|
-
inputSearchProps: InputSearchProps
|
|
33
|
-
useAnimationSearch: Boolean =
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
opacityAni: Float,
|
|
39
|
+
inputSearchProps: InputSearchProps?,
|
|
40
|
+
useAnimationSearch: Boolean = true,
|
|
41
|
+
scrollState: Int,
|
|
42
|
+
headerRightWidth: Dp,
|
|
43
|
+
isBack: Boolean,
|
|
44
|
+
statusBarHeight: Dp,
|
|
45
|
+
backgroundColor: Color
|
|
46
|
+
) {
|
|
47
|
+
val animations = useHeaderSearchAnimation(
|
|
48
|
+
opacityAni = opacityAni,
|
|
49
|
+
scrollState = scrollState,
|
|
50
|
+
headerRightWidth = headerRightWidth,
|
|
51
|
+
statusBarHeight = statusBarHeight,
|
|
52
|
+
isBack = isBack
|
|
53
|
+
)
|
|
54
|
+
|
|
36
55
|
Box(
|
|
37
|
-
modifier = Modifier.fillMaxWidth()
|
|
56
|
+
modifier = Modifier.fillMaxWidth()
|
|
57
|
+
.height(animations.height.dp)
|
|
38
58
|
) {
|
|
39
59
|
Box(
|
|
40
60
|
modifier = Modifier
|
|
41
61
|
.fillMaxWidth()
|
|
42
62
|
.height(154.dp)
|
|
43
|
-
.alpha(
|
|
63
|
+
.alpha(opacityAni)
|
|
44
64
|
.background(
|
|
45
65
|
Brush.linearGradient(
|
|
46
66
|
colors = listOf(
|
|
@@ -70,6 +90,19 @@ fun HeaderExtended(
|
|
|
70
90
|
}
|
|
71
91
|
}
|
|
72
92
|
|
|
93
|
+
Box(
|
|
94
|
+
modifier = Modifier
|
|
95
|
+
.fillMaxWidth()
|
|
96
|
+
.alpha(1f - opacityAni)
|
|
97
|
+
.height(statusBarHeight + 52.dp)
|
|
98
|
+
.background(
|
|
99
|
+
AppTheme.current.colors.background.surface
|
|
100
|
+
)
|
|
101
|
+
.bottomBorder(
|
|
102
|
+
strokeWidth = 1.dp,
|
|
103
|
+
color = AppTheme.current.colors.border.default
|
|
104
|
+
)
|
|
105
|
+
)
|
|
73
106
|
if (inputSearchProps != null && useAnimationSearch) {
|
|
74
107
|
Box(
|
|
75
108
|
modifier = Modifier
|
|
@@ -98,5 +131,4 @@ fun HeaderExtended(
|
|
|
98
131
|
}
|
|
99
132
|
}
|
|
100
133
|
}
|
|
101
|
-
}
|
|
102
|
-
|
|
134
|
+
}
|
|
@@ -79,12 +79,12 @@ object Spacing {
|
|
|
79
79
|
|
|
80
80
|
@Composable
|
|
81
81
|
fun HeaderRight(
|
|
82
|
-
|
|
82
|
+
headerRight: HeaderRightData? = null,
|
|
83
83
|
) {
|
|
84
84
|
Row(
|
|
85
85
|
verticalAlignment = Alignment.CenterVertically,
|
|
86
86
|
) {
|
|
87
|
-
ToolkitHeaderRight(headerRight =
|
|
87
|
+
ToolkitHeaderRight(headerRight = headerRight)
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -180,8 +180,6 @@ fun ToolkitHeaderRight(headerRight: HeaderRightData? = null) {
|
|
|
180
180
|
group.items.any { it.showBadge }
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
if (context === null) return
|
|
184
|
-
|
|
185
183
|
Row(
|
|
186
184
|
verticalAlignment = Alignment.CenterVertically
|
|
187
185
|
) {
|
|
@@ -68,6 +68,7 @@ fun Screen(
|
|
|
68
68
|
layoutOffset: Dp = 56.dp,
|
|
69
69
|
inputSearchProps: InputSearchProps? = null,
|
|
70
70
|
useAnimationSearch: Boolean = false,
|
|
71
|
+
headerRightWidth: Dp = 0.dp,
|
|
71
72
|
content: @Composable () -> Unit,
|
|
72
73
|
) {
|
|
73
74
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
@@ -84,7 +85,7 @@ fun Screen(
|
|
|
84
85
|
val bottomPadding = min(indicator, 21.dp)
|
|
85
86
|
|
|
86
87
|
val opacity by animateFloatAsState(
|
|
87
|
-
targetValue = ((scrollState.value /
|
|
88
|
+
targetValue = ((scrollState.value / 52f)).coerceIn(0f, 1f),
|
|
88
89
|
)
|
|
89
90
|
|
|
90
91
|
val headerAnimated =
|
|
@@ -94,15 +95,16 @@ fun Screen(
|
|
|
94
95
|
|
|
95
96
|
Box(
|
|
96
97
|
Modifier.fillMaxSize()
|
|
97
|
-
.background(AppTheme.current.colors.background.
|
|
98
|
+
.background(backgroundColor ?: AppTheme.current.colors.background.default)
|
|
98
99
|
) {
|
|
99
100
|
|
|
100
101
|
if (animatedHeader === null) {
|
|
101
102
|
HeaderBackground(
|
|
102
103
|
headerType = headerType,
|
|
103
104
|
scrollState = scrollState.value,
|
|
104
|
-
inputSearchProps
|
|
105
|
-
useAnimationSearch = useAnimationSearch
|
|
105
|
+
inputSearchProps= inputSearchProps,
|
|
106
|
+
useAnimationSearch = useAnimationSearch,
|
|
107
|
+
headerRightWidth = headerRightWidth
|
|
106
108
|
)
|
|
107
109
|
} else {
|
|
108
110
|
Box(
|
|
@@ -114,8 +116,9 @@ fun Screen(
|
|
|
114
116
|
isBack = isBack,
|
|
115
117
|
headerType = headerType,
|
|
116
118
|
scrollState = scrollState.value,
|
|
117
|
-
inputSearchProps
|
|
118
|
-
useAnimationSearch = useAnimationSearch
|
|
119
|
+
inputSearchProps= inputSearchProps,
|
|
120
|
+
useAnimationSearch = useAnimationSearch,
|
|
121
|
+
headerRightWidth = headerRightWidth
|
|
119
122
|
)
|
|
120
123
|
}
|
|
121
124
|
}
|
|
@@ -130,7 +133,7 @@ fun Screen(
|
|
|
130
133
|
animatedHeader = animatedHeader,
|
|
131
134
|
inputSearchProps = inputSearchProps,
|
|
132
135
|
scrollState = scrollState.value,
|
|
133
|
-
useAnimationSearch = useAnimationSearch
|
|
136
|
+
useAnimationSearch = useAnimationSearch,
|
|
134
137
|
)
|
|
135
138
|
|
|
136
139
|
Column(
|
|
@@ -155,11 +158,7 @@ fun Screen(
|
|
|
155
158
|
verticalArrangement = verticalArrangement,
|
|
156
159
|
horizontalAlignment = horizontalAlignment
|
|
157
160
|
) {
|
|
158
|
-
Box
|
|
159
|
-
modifier = Modifier.background(
|
|
160
|
-
backgroundColor ?: AppTheme.current.colors.background.default
|
|
161
|
-
)
|
|
162
|
-
) {
|
|
161
|
+
Box {
|
|
163
162
|
headerAnimated()
|
|
164
163
|
Column {
|
|
165
164
|
if (animatedHeader !== null) {
|
|
@@ -3,11 +3,13 @@ package vn.momo.kits.application
|
|
|
3
3
|
import androidx.compose.animation.animateColorAsState
|
|
4
4
|
import androidx.compose.animation.core.animateFloatAsState
|
|
5
5
|
import androidx.compose.runtime.Composable
|
|
6
|
+
import androidx.compose.runtime.getValue
|
|
6
7
|
import androidx.compose.ui.graphics.Color
|
|
7
8
|
import androidx.compose.ui.unit.Dp
|
|
9
|
+
import androidx.compose.ui.unit.dp
|
|
8
10
|
import vn.momo.kits.const.AppTheme
|
|
9
11
|
import vn.momo.kits.const.Colors
|
|
10
|
-
import
|
|
12
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
11
13
|
|
|
12
14
|
data class HeaderAnimations(
|
|
13
15
|
val opacity: Float,
|
|
@@ -17,40 +19,46 @@ data class HeaderAnimations(
|
|
|
17
19
|
val height: Float
|
|
18
20
|
)
|
|
19
21
|
|
|
22
|
+
private const val SCREEN_PADDING = 12
|
|
23
|
+
private const val BACK_WIDTH = 28
|
|
24
|
+
|
|
20
25
|
@Composable
|
|
21
26
|
fun useHeaderSearchAnimation(
|
|
27
|
+
opacityAni: Float,
|
|
22
28
|
scrollState: Int,
|
|
29
|
+
headerRightWidth: Dp,
|
|
23
30
|
statusBarHeight: Dp,
|
|
24
|
-
|
|
25
|
-
searchWidth: Int,
|
|
26
|
-
headerRightWidth: Dp
|
|
31
|
+
isBack: Boolean
|
|
27
32
|
): HeaderAnimations {
|
|
28
|
-
val
|
|
29
|
-
|
|
30
|
-
)
|
|
33
|
+
val screenWidth = getScreenDimensions().width
|
|
34
|
+
val leftPosition = if (isBack) (BACK_WIDTH + 20).dp else 20.dp
|
|
35
|
+
val searchWidth = screenWidth - (SCREEN_PADDING * 2)
|
|
31
36
|
|
|
32
37
|
val backgroundSearch by animateColorAsState(
|
|
33
38
|
targetValue = animateColor(
|
|
34
39
|
AppTheme.current.colors.background.default,
|
|
35
40
|
Colors.black_01,
|
|
36
41
|
opacityAni
|
|
37
|
-
)
|
|
42
|
+
),
|
|
38
43
|
)
|
|
39
44
|
|
|
40
45
|
val animatedTranslateX by animateFloatAsState(
|
|
41
|
-
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12
|
|
46
|
+
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12,
|
|
42
47
|
)
|
|
43
48
|
|
|
44
49
|
val animatedWidth by animateFloatAsState(
|
|
45
|
-
targetValue = (scrollState / 52f).coerceIn(
|
|
46
|
-
|
|
50
|
+
targetValue = (scrollState / 52f).coerceIn(
|
|
51
|
+
0f,
|
|
52
|
+
1f
|
|
53
|
+
) * ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth,
|
|
47
54
|
)
|
|
48
55
|
|
|
49
56
|
val animatedHeight by animateFloatAsState(
|
|
50
|
-
targetValue = (1 - (scrollState / 52f).coerceIn(
|
|
51
|
-
|
|
57
|
+
targetValue = (1 - (scrollState / 52f).coerceIn(
|
|
58
|
+
0f,
|
|
59
|
+
1f
|
|
60
|
+
)) * (statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52),
|
|
52
61
|
)
|
|
53
|
-
|
|
54
62
|
return HeaderAnimations(
|
|
55
63
|
opacity = opacityAni,
|
|
56
64
|
backgroundSearch = backgroundSearch,
|
package/local.properties
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
# Location of the SDK. This is only used by Gradle.
|
|
5
5
|
# For customization when using a Version Control System, please read the
|
|
6
6
|
# header note.
|
|
7
|
-
#
|
|
8
|
-
sdk.dir=/Users/
|
|
7
|
+
#Sun Mar 02 11:30:14 ICT 2025
|
|
8
|
+
sdk.dir=/Users/nguyenhoangson/Library/Android/sdk
|