@momo-kits/native-kits 0.113.2-beta.15 → 0.113.2-beta.16
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 +57 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +25 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +4 -5
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +9 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +4 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +1 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +12 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +14 -22
- package/ios/Application/Components.swift +2 -0
- package/local.properties +2 -2
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.animateColorAsState
|
|
3
4
|
import androidx.compose.foundation.background
|
|
4
5
|
import androidx.compose.foundation.border
|
|
5
6
|
import androidx.compose.foundation.clickable
|
|
@@ -23,6 +24,7 @@ import androidx.compose.runtime.setValue
|
|
|
23
24
|
import androidx.compose.runtime.snapshotFlow
|
|
24
25
|
import androidx.compose.ui.Alignment
|
|
25
26
|
import androidx.compose.ui.Modifier
|
|
27
|
+
import androidx.compose.ui.graphics.Color
|
|
26
28
|
import androidx.compose.ui.graphics.graphicsLayer
|
|
27
29
|
import androidx.compose.ui.semantics.semantics
|
|
28
30
|
import androidx.compose.ui.semantics.testTag
|
|
@@ -40,6 +42,15 @@ import vn.momo.kits.const.Spacing
|
|
|
40
42
|
import vn.momo.kits.modifier.setAutomationId
|
|
41
43
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
42
44
|
|
|
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
|
+
|
|
43
54
|
@Composable
|
|
44
55
|
fun Header(
|
|
45
56
|
headerType: HeaderType = HeaderType.DEFAULT,
|
|
@@ -66,15 +77,24 @@ fun Header(
|
|
|
66
77
|
.collect { fraction -> colorFraction = fraction }
|
|
67
78
|
}
|
|
68
79
|
|
|
69
|
-
val backgroundSearch
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
val backgroundSearch by animateColorAsState(
|
|
81
|
+
targetValue = animateColor(
|
|
82
|
+
AppTheme.current.colors.background.surface,
|
|
83
|
+
AppTheme.current.colors.background.default,
|
|
84
|
+
colorFraction
|
|
85
|
+
)
|
|
73
86
|
)
|
|
74
87
|
|
|
88
|
+
val backgroundColor = if (scrollState == 0) {
|
|
89
|
+
Color.Transparent
|
|
90
|
+
} else {
|
|
91
|
+
AppTheme.current.colors.background.surface
|
|
92
|
+
}
|
|
93
|
+
|
|
75
94
|
if (headerType != HeaderType.NONE) {
|
|
76
95
|
BoxWithConstraints(
|
|
77
96
|
Modifier.height(statusBarHeight + 52.dp)
|
|
97
|
+
.background(backgroundColor)
|
|
78
98
|
.fillMaxWidth()
|
|
79
99
|
.zIndex(10f),
|
|
80
100
|
contentAlignment = Alignment.BottomCenter
|
|
@@ -118,9 +138,9 @@ fun Header(
|
|
|
118
138
|
}
|
|
119
139
|
}
|
|
120
140
|
|
|
121
|
-
if (useAnimationSearch || inputSearchProps == null) {
|
|
141
|
+
if ((useAnimationSearch && inputSearchProps != null) || inputSearchProps == null) {
|
|
122
142
|
Box(Modifier.graphicsLayer {
|
|
123
|
-
alpha = if (
|
|
143
|
+
alpha = if (useAnimationSearch) 1f - (opacity ?: 1f) else 1f
|
|
124
144
|
}) {
|
|
125
145
|
headerRight?.invoke()
|
|
126
146
|
}
|
|
@@ -136,32 +156,40 @@ fun Header(
|
|
|
136
156
|
) {
|
|
137
157
|
if (goBack != null && titlePosition == TitlePosition.LEFT) {
|
|
138
158
|
Spacer(Modifier.width(40.dp))
|
|
159
|
+
}
|
|
160
|
+
if (inputSearchProps != null && !useAnimationSearch) {
|
|
161
|
+
InputSearch(inputSearchProps = inputSearchProps.copy(backgroundColor = backgroundSearch))
|
|
139
162
|
} else {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
modifier = Modifier.semantics {
|
|
158
|
-
testTag = "title_navigation_header"
|
|
159
|
-
}
|
|
160
|
-
)
|
|
161
|
-
}
|
|
163
|
+
Box(
|
|
164
|
+
Modifier.weight(1f).graphicsLayer {
|
|
165
|
+
alpha = if (useAnimationSearch && inputSearchProps != null) {
|
|
166
|
+
1f - (opacity ?: 1f)
|
|
167
|
+
} else {
|
|
168
|
+
if (animatedHeader !== null) opacity ?: 1f else 1f
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
contentAlignment = if (titlePosition == TitlePosition.LEFT) Alignment.TopStart else Alignment.Center
|
|
172
|
+
) {
|
|
173
|
+
HeaderTitle(
|
|
174
|
+
title = title,
|
|
175
|
+
color = tintIconColor,
|
|
176
|
+
modifier = Modifier.semantics {
|
|
177
|
+
testTag = "title_navigation_header"
|
|
178
|
+
}
|
|
179
|
+
)
|
|
162
180
|
}
|
|
163
181
|
}
|
|
164
182
|
}
|
|
165
183
|
}
|
|
166
184
|
}
|
|
167
|
-
}
|
|
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
|
+
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.animateColorAsState
|
|
4
|
-
import androidx.compose.animation.core.animateFloatAsState
|
|
5
3
|
import androidx.compose.foundation.layout.Box
|
|
6
4
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
7
5
|
import androidx.compose.runtime.Composable
|
|
8
|
-
import androidx.compose.runtime.getValue
|
|
9
6
|
import androidx.compose.ui.Modifier
|
|
10
7
|
import androidx.compose.ui.graphics.Color
|
|
11
8
|
import androidx.compose.ui.unit.Dp
|
|
@@ -13,25 +10,11 @@ import androidx.compose.ui.unit.dp
|
|
|
13
10
|
import vn.momo.kits.components.InputSearchProps
|
|
14
11
|
import vn.momo.kits.const.AppStatusBar
|
|
15
12
|
import vn.momo.kits.const.AppTheme
|
|
13
|
+
import vn.momo.kits.platform.getScreenDimensions
|
|
16
14
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
}
|
|
16
|
+
private const val SCREEN_PADDING = 12
|
|
17
|
+
private const val BACK_WIDTH = 28
|
|
35
18
|
|
|
36
19
|
@Composable
|
|
37
20
|
fun HeaderBackground(
|
|
@@ -43,39 +26,41 @@ fun HeaderBackground(
|
|
|
43
26
|
useAnimationSearch: Boolean = false
|
|
44
27
|
) {
|
|
45
28
|
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)
|
|
46
32
|
|
|
47
|
-
val
|
|
48
|
-
|
|
33
|
+
val animations = useHeaderSearchAnimation(
|
|
34
|
+
scrollState = scrollState,
|
|
35
|
+
statusBarHeight = statusBarHeight,
|
|
36
|
+
leftPosition = leftPosition,
|
|
37
|
+
searchWidth = searchWidth,
|
|
38
|
+
headerRightWidth = headerRightWidth
|
|
49
39
|
)
|
|
50
40
|
|
|
51
|
-
val backgroundColor
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
),
|
|
57
|
-
)
|
|
41
|
+
val backgroundColor = if (scrollState == 0) {
|
|
42
|
+
Color.Transparent
|
|
43
|
+
} else {
|
|
44
|
+
AppTheme.current.colors.background.surface
|
|
45
|
+
}
|
|
58
46
|
|
|
59
47
|
when (headerType) {
|
|
60
48
|
HeaderType.DEFAULT -> {
|
|
49
|
+
val height = statusBarHeight + 52.dp
|
|
61
50
|
HeaderDefault(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
backgroundColor = backgroundColor
|
|
51
|
+
height = height,
|
|
52
|
+
animations = animations,
|
|
53
|
+
backgroundColor = backgroundColor
|
|
65
54
|
)
|
|
66
55
|
}
|
|
67
56
|
|
|
68
57
|
HeaderType.EXTENDED -> {
|
|
69
|
-
|
|
70
|
-
|
|
58
|
+
HeaderExtended(
|
|
59
|
+
animations = animations,
|
|
71
60
|
inputSearchProps = inputSearchProps,
|
|
72
|
-
headerRightWidth = headerRightWidth,
|
|
73
61
|
useAnimationSearch = useAnimationSearch,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
statusBarHeight = statusBarHeight,
|
|
77
|
-
backgroundColor = backgroundColor,
|
|
78
|
-
)
|
|
62
|
+
backgroundColor = backgroundColor
|
|
63
|
+
)
|
|
79
64
|
}
|
|
80
65
|
|
|
81
66
|
else -> {
|
|
@@ -21,11 +21,10 @@ import vn.momo.kits.utils.bottomBorder
|
|
|
21
21
|
|
|
22
22
|
@Composable
|
|
23
23
|
fun HeaderDefault(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
height: Dp,
|
|
25
|
+
backgroundColor: Color,
|
|
26
|
+
animations: HeaderAnimations
|
|
27
27
|
) {
|
|
28
|
-
val height = statusBarHeight + 52.dp
|
|
29
28
|
Box(
|
|
30
29
|
modifier = Modifier.fillMaxWidth().height(height)
|
|
31
30
|
.background(backgroundColor)
|
|
@@ -38,7 +37,7 @@ fun HeaderDefault(
|
|
|
38
37
|
modifier = Modifier
|
|
39
38
|
.height(height)
|
|
40
39
|
.fillMaxWidth()
|
|
41
|
-
.alpha(
|
|
40
|
+
.alpha(animations.opacity)
|
|
42
41
|
.background(
|
|
43
42
|
Brush.linearGradient(
|
|
44
43
|
colors = listOf(
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
package vn.momo.kits.application
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.animateColorAsState
|
|
4
|
-
import androidx.compose.animation.core.animateFloatAsState
|
|
5
3
|
import androidx.compose.foundation.background
|
|
6
4
|
import androidx.compose.foundation.layout.Box
|
|
7
5
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@@ -11,7 +9,6 @@ import androidx.compose.foundation.layout.padding
|
|
|
11
9
|
import androidx.compose.foundation.layout.width
|
|
12
10
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
13
11
|
import androidx.compose.runtime.Composable
|
|
14
|
-
import androidx.compose.runtime.getValue
|
|
15
12
|
import androidx.compose.ui.Alignment
|
|
16
13
|
import androidx.compose.ui.Modifier
|
|
17
14
|
import androidx.compose.ui.draw.alpha
|
|
@@ -20,47 +17,30 @@ import androidx.compose.ui.graphics.Brush
|
|
|
20
17
|
import androidx.compose.ui.graphics.Color
|
|
21
18
|
import androidx.compose.ui.layout.ContentScale
|
|
22
19
|
import androidx.compose.ui.platform.LocalDensity
|
|
23
|
-
import androidx.compose.ui.unit.Dp
|
|
24
20
|
import androidx.compose.ui.unit.dp
|
|
25
21
|
import vn.momo.kits.components.Image
|
|
26
22
|
import vn.momo.kits.components.InputSearch
|
|
27
23
|
import vn.momo.kits.components.InputSearchProps
|
|
28
24
|
import vn.momo.kits.components.Options
|
|
29
25
|
import vn.momo.kits.const.AppTheme
|
|
30
|
-
import vn.momo.kits.const.Colors
|
|
31
26
|
import vn.momo.kits.const.Radius
|
|
32
27
|
import vn.momo.kits.const.Spacing
|
|
33
|
-
import vn.momo.kits.platform.getScreenDimensions
|
|
34
|
-
import vn.momo.kits.utils.bottomBorder
|
|
35
28
|
|
|
36
29
|
@Composable
|
|
37
30
|
fun HeaderExtended(
|
|
38
|
-
|
|
39
|
-
inputSearchProps: InputSearchProps
|
|
40
|
-
useAnimationSearch: Boolean =
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
31
|
+
animations: HeaderAnimations,
|
|
32
|
+
inputSearchProps: InputSearchProps? = null,
|
|
33
|
+
useAnimationSearch: Boolean = false,
|
|
34
|
+
backgroundColor: Color = Color.Transparent
|
|
35
|
+
){
|
|
55
36
|
Box(
|
|
56
|
-
modifier = Modifier.fillMaxWidth()
|
|
57
|
-
.height(animations.height.dp)
|
|
37
|
+
modifier = Modifier.fillMaxWidth().height(animations.height.dp)
|
|
58
38
|
) {
|
|
59
39
|
Box(
|
|
60
40
|
modifier = Modifier
|
|
61
41
|
.fillMaxWidth()
|
|
62
42
|
.height(154.dp)
|
|
63
|
-
.alpha(
|
|
43
|
+
.alpha(animations.opacity)
|
|
64
44
|
.background(
|
|
65
45
|
Brush.linearGradient(
|
|
66
46
|
colors = listOf(
|
|
@@ -90,19 +70,6 @@ fun HeaderExtended(
|
|
|
90
70
|
}
|
|
91
71
|
}
|
|
92
72
|
|
|
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
|
-
)
|
|
106
73
|
if (inputSearchProps != null && useAnimationSearch) {
|
|
107
74
|
Box(
|
|
108
75
|
modifier = Modifier
|
|
@@ -131,4 +98,5 @@ fun HeaderExtended(
|
|
|
131
98
|
}
|
|
132
99
|
}
|
|
133
100
|
}
|
|
134
|
-
}
|
|
101
|
+
}
|
|
102
|
+
|
|
@@ -79,12 +79,12 @@ object Spacing {
|
|
|
79
79
|
|
|
80
80
|
@Composable
|
|
81
81
|
fun HeaderRight(
|
|
82
|
-
|
|
82
|
+
data: HeaderRightData? = null,
|
|
83
83
|
) {
|
|
84
84
|
Row(
|
|
85
85
|
verticalAlignment = Alignment.CenterVertically,
|
|
86
86
|
) {
|
|
87
|
-
ToolkitHeaderRight(headerRight =
|
|
87
|
+
ToolkitHeaderRight(headerRight = data)
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -180,6 +180,8 @@ fun ToolkitHeaderRight(headerRight: HeaderRightData? = null) {
|
|
|
180
180
|
group.items.any { it.showBadge }
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
+
if (context === null) return
|
|
184
|
+
|
|
183
185
|
Row(
|
|
184
186
|
verticalAlignment = Alignment.CenterVertically
|
|
185
187
|
) {
|
|
@@ -68,7 +68,6 @@ fun Screen(
|
|
|
68
68
|
layoutOffset: Dp = 56.dp,
|
|
69
69
|
inputSearchProps: InputSearchProps? = null,
|
|
70
70
|
useAnimationSearch: Boolean = false,
|
|
71
|
-
headerRightWidth: Dp = 0.dp,
|
|
72
71
|
content: @Composable () -> Unit,
|
|
73
72
|
) {
|
|
74
73
|
val statusBarHeight = AppStatusBar.current ?: getStatusBarHeight()
|
|
@@ -85,7 +84,7 @@ fun Screen(
|
|
|
85
84
|
val bottomPadding = min(indicator, 21.dp)
|
|
86
85
|
|
|
87
86
|
val opacity by animateFloatAsState(
|
|
88
|
-
targetValue = ((scrollState.value /
|
|
87
|
+
targetValue = ((scrollState.value / 114f)).coerceIn(0f, 1f)
|
|
89
88
|
)
|
|
90
89
|
|
|
91
90
|
val headerAnimated =
|
|
@@ -95,16 +94,15 @@ fun Screen(
|
|
|
95
94
|
|
|
96
95
|
Box(
|
|
97
96
|
Modifier.fillMaxSize()
|
|
98
|
-
.background(
|
|
97
|
+
.background(AppTheme.current.colors.background.surface)
|
|
99
98
|
) {
|
|
100
99
|
|
|
101
100
|
if (animatedHeader === null) {
|
|
102
101
|
HeaderBackground(
|
|
103
102
|
headerType = headerType,
|
|
104
103
|
scrollState = scrollState.value,
|
|
105
|
-
inputSearchProps= inputSearchProps,
|
|
106
|
-
useAnimationSearch = useAnimationSearch
|
|
107
|
-
headerRightWidth = headerRightWidth
|
|
104
|
+
inputSearchProps = inputSearchProps,
|
|
105
|
+
useAnimationSearch = useAnimationSearch
|
|
108
106
|
)
|
|
109
107
|
} else {
|
|
110
108
|
Box(
|
|
@@ -116,9 +114,8 @@ fun Screen(
|
|
|
116
114
|
isBack = isBack,
|
|
117
115
|
headerType = headerType,
|
|
118
116
|
scrollState = scrollState.value,
|
|
119
|
-
inputSearchProps= inputSearchProps,
|
|
120
|
-
useAnimationSearch = useAnimationSearch
|
|
121
|
-
headerRightWidth = headerRightWidth
|
|
117
|
+
inputSearchProps = inputSearchProps,
|
|
118
|
+
useAnimationSearch = useAnimationSearch
|
|
122
119
|
)
|
|
123
120
|
}
|
|
124
121
|
}
|
|
@@ -133,7 +130,7 @@ fun Screen(
|
|
|
133
130
|
animatedHeader = animatedHeader,
|
|
134
131
|
inputSearchProps = inputSearchProps,
|
|
135
132
|
scrollState = scrollState.value,
|
|
136
|
-
useAnimationSearch = useAnimationSearch
|
|
133
|
+
useAnimationSearch = useAnimationSearch
|
|
137
134
|
)
|
|
138
135
|
|
|
139
136
|
Column(
|
|
@@ -158,7 +155,11 @@ fun Screen(
|
|
|
158
155
|
verticalArrangement = verticalArrangement,
|
|
159
156
|
horizontalAlignment = horizontalAlignment
|
|
160
157
|
) {
|
|
161
|
-
Box
|
|
158
|
+
Box(
|
|
159
|
+
modifier = Modifier.background(
|
|
160
|
+
backgroundColor ?: AppTheme.current.colors.background.default
|
|
161
|
+
)
|
|
162
|
+
) {
|
|
162
163
|
headerAnimated()
|
|
163
164
|
Column {
|
|
164
165
|
if (animatedHeader !== null) {
|
|
@@ -3,13 +3,11 @@ 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
|
|
7
6
|
import androidx.compose.ui.graphics.Color
|
|
8
7
|
import androidx.compose.ui.unit.Dp
|
|
9
|
-
import androidx.compose.ui.unit.dp
|
|
10
8
|
import vn.momo.kits.const.AppTheme
|
|
11
9
|
import vn.momo.kits.const.Colors
|
|
12
|
-
import
|
|
10
|
+
import androidx.compose.runtime.getValue
|
|
13
11
|
|
|
14
12
|
data class HeaderAnimations(
|
|
15
13
|
val opacity: Float,
|
|
@@ -19,46 +17,40 @@ data class HeaderAnimations(
|
|
|
19
17
|
val height: Float
|
|
20
18
|
)
|
|
21
19
|
|
|
22
|
-
private const val SCREEN_PADDING = 12
|
|
23
|
-
private const val BACK_WIDTH = 28
|
|
24
|
-
|
|
25
20
|
@Composable
|
|
26
21
|
fun useHeaderSearchAnimation(
|
|
27
|
-
opacityAni: Float,
|
|
28
22
|
scrollState: Int,
|
|
29
|
-
headerRightWidth: Dp,
|
|
30
23
|
statusBarHeight: Dp,
|
|
31
|
-
|
|
24
|
+
leftPosition: Dp,
|
|
25
|
+
searchWidth: Int,
|
|
26
|
+
headerRightWidth: Dp
|
|
32
27
|
): HeaderAnimations {
|
|
33
|
-
val
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
val opacityAni by animateFloatAsState(
|
|
29
|
+
targetValue = (1 - (scrollState / 52f)).coerceIn(0f, 1f)
|
|
30
|
+
)
|
|
36
31
|
|
|
37
32
|
val backgroundSearch by animateColorAsState(
|
|
38
33
|
targetValue = animateColor(
|
|
39
34
|
AppTheme.current.colors.background.default,
|
|
40
35
|
Colors.black_01,
|
|
41
36
|
opacityAni
|
|
42
|
-
)
|
|
37
|
+
)
|
|
43
38
|
)
|
|
44
39
|
|
|
45
40
|
val animatedTranslateX by animateFloatAsState(
|
|
46
|
-
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12
|
|
41
|
+
targetValue = (scrollState / 52f).coerceIn(0f, 1f) * (leftPosition.value - 12) + 12
|
|
47
42
|
)
|
|
48
43
|
|
|
49
44
|
val animatedWidth by animateFloatAsState(
|
|
50
|
-
targetValue = (scrollState / 52f).coerceIn(
|
|
51
|
-
|
|
52
|
-
1f
|
|
53
|
-
) * ((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth,
|
|
45
|
+
targetValue = (scrollState / 52f).coerceIn(0f, 1f) *
|
|
46
|
+
((searchWidth - leftPosition.value - headerRightWidth.value + 12) - searchWidth) + searchWidth
|
|
54
47
|
)
|
|
55
48
|
|
|
56
49
|
val animatedHeight by animateFloatAsState(
|
|
57
|
-
targetValue = (1 - (scrollState / 52f).coerceIn(
|
|
58
|
-
|
|
59
|
-
1f
|
|
60
|
-
)) * (statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52),
|
|
50
|
+
targetValue = (1 - (scrollState / 52f).coerceIn(0f, 1f)) *
|
|
51
|
+
(statusBarHeight.value + 94 - (statusBarHeight.value + 52)) + (statusBarHeight.value + 52)
|
|
61
52
|
)
|
|
53
|
+
|
|
62
54
|
return HeaderAnimations(
|
|
63
55
|
opacity = opacityAni,
|
|
64
56
|
backgroundSearch = backgroundSearch,
|
|
@@ -203,7 +203,9 @@ public struct Header: View {
|
|
|
203
203
|
Text(title)
|
|
204
204
|
.font(.headline)
|
|
205
205
|
.foregroundColor(tintIconColor)
|
|
206
|
+
.frame(maxWidth: UIScreen.main.bounds.width - 172)
|
|
206
207
|
.frame(maxWidth: titlePosition == .center ? .infinity : nil, alignment: titlePosition == .center ? .center : .leading)
|
|
208
|
+
.lineLimit(1)
|
|
207
209
|
}
|
|
208
210
|
Spacer()
|
|
209
211
|
}
|
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
|
+
#Thu Jan 09 10:43:10 ICT 2025
|
|
8
|
+
sdk.dir=/Users/sophia/Library/Android/sdk
|