@momo-kits/native-kits 0.167.1-beta.19-debug → 0.167.1-beta.20-debug
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/build.gradle.kts +5 -10
- package/compose/build.gradle.kts.backup +4 -9
- package/compose/compose.podspec +1 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +9 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +90 -73
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +29 -34
- package/gradle.properties +1 -1
- package/ios/native-kits.podspec +1 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/package.json +1 -1
package/compose/build.gradle.kts
CHANGED
|
@@ -40,7 +40,7 @@ kotlin {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
cocoapods {
|
|
43
|
-
version = "0.167.1-beta.
|
|
43
|
+
version = "0.167.1-beta.20-debug"
|
|
44
44
|
summary = "IOS Shared module"
|
|
45
45
|
homepage = "https://momo.vn"
|
|
46
46
|
ios.deploymentTarget = "15.0"
|
|
@@ -189,15 +189,10 @@ compose {
|
|
|
189
189
|
// }
|
|
190
190
|
// }
|
|
191
191
|
|
|
192
|
-
// KGP's synthetic Podfile only raises pods to
|
|
193
|
-
tasks.
|
|
192
|
+
// Xcode 27 rejects iOS < 15; KGP's synthetic Podfile only raises pods to 12 (KT-57741), leaving lottie-ios at 13.
|
|
193
|
+
tasks.named("podGenIos") {
|
|
194
194
|
doLast {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
val text = podfile.readText()
|
|
198
|
-
if ("IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'" !in text) {
|
|
199
|
-
podfile.writeText(text.replace(signingLine, "$signingLine\n config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'"))
|
|
200
|
-
}
|
|
201
|
-
}
|
|
195
|
+
val podfile = layout.buildDirectory.file("cocoapods/synthetic/ios/Podfile").get().asFile
|
|
196
|
+
podfile.writeText(podfile.readText().replace("major < 12 ||", "major < 15 ||").replace("#{12}", "#{15}"))
|
|
202
197
|
}
|
|
203
198
|
}
|
|
@@ -189,15 +189,10 @@ mavenPublishing {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
// KGP's synthetic Podfile only raises pods to
|
|
193
|
-
tasks.
|
|
192
|
+
// Xcode 27 rejects iOS < 15; KGP's synthetic Podfile only raises pods to 12 (KT-57741), leaving lottie-ios at 13.
|
|
193
|
+
tasks.named("podGenIos") {
|
|
194
194
|
doLast {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
val text = podfile.readText()
|
|
198
|
-
if ("IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'" !in text) {
|
|
199
|
-
podfile.writeText(text.replace(signingLine, "$signingLine\n config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'"))
|
|
200
|
-
}
|
|
201
|
-
}
|
|
195
|
+
val podfile = layout.buildDirectory.file("cocoapods/synthetic/ios/Podfile").get().asFile
|
|
196
|
+
podfile.writeText(podfile.readText().replace("major < 12 ||", "major < 15 ||").replace("#{12}", "#{15}"))
|
|
202
197
|
}
|
|
203
198
|
}
|
package/compose/compose.podspec
CHANGED
|
@@ -67,6 +67,7 @@ import vn.momo.kits.navigation.component.HeaderBackground
|
|
|
67
67
|
import vn.momo.kits.navigation.component.HeaderRight
|
|
68
68
|
import vn.momo.kits.navigation.component.HeaderType
|
|
69
69
|
import vn.momo.kits.navigation.component.InputSearchType
|
|
70
|
+
import vn.momo.kits.navigation.bottomtab.LocalBottomTabFocused
|
|
70
71
|
import vn.momo.kits.platform.BackHandler
|
|
71
72
|
import vn.momo.kits.platform.supportsImePadding
|
|
72
73
|
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
@@ -109,20 +110,24 @@ internal fun StackScreen(
|
|
|
109
110
|
val isBottomTabChild = bottomTabIndex != -1
|
|
110
111
|
val isBottomTabRoot = navigation.isBottomTabRoot
|
|
111
112
|
|
|
113
|
+
// A mounted-but-hidden bottom tab tracks again each time it is focused (RN useFocusEffect).
|
|
114
|
+
val tabFocused = LocalBottomTabFocused.current
|
|
115
|
+
|
|
112
116
|
// Auto tracking state
|
|
113
|
-
val trackingState = remember {
|
|
117
|
+
val trackingState = remember(tabFocused) {
|
|
114
118
|
ScreenTrackingState().apply {
|
|
115
119
|
time = Clock.System.now().toEpochMilliseconds()
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
// Determine action: push or back
|
|
120
|
-
val action = remember {
|
|
124
|
+
val action = remember(tabFocused) {
|
|
121
125
|
if (ScreenTracker.getLastScreenName() != null) "push" else "back"
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
// Auto tracking effects
|
|
125
|
-
LaunchedEffect(name) {
|
|
129
|
+
LaunchedEffect(name, tabFocused) {
|
|
130
|
+
if (!tabFocused) return@LaunchedEffect
|
|
126
131
|
// Track screen navigated immediately
|
|
127
132
|
ScreenTracker.trackScreenNavigated(
|
|
128
133
|
maxApi = maxApi,
|
|
@@ -169,7 +174,7 @@ internal fun StackScreen(
|
|
|
169
174
|
val footerHeightPx = remember { mutableIntStateOf(0) }
|
|
170
175
|
val headerRightWidthPx = remember { mutableIntStateOf(0) }
|
|
171
176
|
|
|
172
|
-
if (navigation.options.scrollData.scrollToTopCallback != null) {
|
|
177
|
+
if (tabFocused && navigation.options.scrollData.scrollToTopCallback != null) {
|
|
173
178
|
RegisterScrollToTop(navigation.options.scrollData.scrollToTopCallback)
|
|
174
179
|
}
|
|
175
180
|
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
package vn.momo.kits.navigation.bottomtab
|
|
2
2
|
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
4
|
+
import androidx.compose.animation.core.AnimationVector1D
|
|
5
|
+
import androidx.compose.animation.core.Easing
|
|
3
6
|
import androidx.compose.animation.core.tween
|
|
4
|
-
import androidx.compose.animation.fadeIn
|
|
5
|
-
import androidx.compose.animation.fadeOut
|
|
6
|
-
import androidx.compose.animation.scaleIn
|
|
7
|
-
import androidx.compose.animation.scaleOut
|
|
8
7
|
import androidx.compose.foundation.background
|
|
9
8
|
import androidx.compose.foundation.layout.*
|
|
10
9
|
import androidx.compose.runtime.Composable
|
|
10
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
11
11
|
import androidx.compose.runtime.DisposableEffect
|
|
12
12
|
import androidx.compose.runtime.LaunchedEffect
|
|
13
|
+
import androidx.compose.runtime.getValue
|
|
14
|
+
import androidx.compose.runtime.key
|
|
15
|
+
import androidx.compose.runtime.mutableIntStateOf
|
|
16
|
+
import androidx.compose.runtime.mutableStateOf
|
|
13
17
|
import androidx.compose.runtime.remember
|
|
18
|
+
import androidx.compose.runtime.saveable.rememberSaveable
|
|
19
|
+
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
|
|
20
|
+
import androidx.compose.runtime.setValue
|
|
21
|
+
import androidx.compose.runtime.staticCompositionLocalOf
|
|
14
22
|
import androidx.compose.ui.Alignment
|
|
15
23
|
import androidx.compose.ui.Modifier
|
|
16
|
-
import androidx.compose.ui.
|
|
17
|
-
import androidx.
|
|
18
|
-
import androidx.
|
|
19
|
-
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
20
|
-
import androidx.navigation.compose.rememberNavController
|
|
24
|
+
import androidx.compose.ui.graphics.graphicsLayer
|
|
25
|
+
import androidx.compose.ui.layout.layout
|
|
26
|
+
import androidx.compose.ui.zIndex
|
|
21
27
|
import vn.momo.kits.const.AppNavigationBar
|
|
22
28
|
import vn.momo.kits.const.AppTheme
|
|
23
29
|
import vn.momo.kits.const.Spacing
|
|
24
30
|
import vn.momo.kits.navigation.KeyboardOptions
|
|
31
|
+
import vn.momo.kits.navigation.LocalMaxApi
|
|
25
32
|
import vn.momo.kits.navigation.LocalNavigation
|
|
26
33
|
import vn.momo.kits.navigation.LocalNavigator
|
|
27
34
|
import vn.momo.kits.navigation.NavigationOptions
|
|
@@ -29,6 +36,17 @@ import vn.momo.kits.navigation.StackScreen
|
|
|
29
36
|
import vn.momo.kits.navigation.component.HeaderType
|
|
30
37
|
import vn.momo.kits.platform.BackHandler
|
|
31
38
|
import vn.momo.kits.platform.reportFloatingArrowBack
|
|
39
|
+
import kotlinx.coroutines.launch
|
|
40
|
+
|
|
41
|
+
private val inOutQuad = Easing { t -> if (t < 0.5f) 2 * t * t else 1 - 2 * (1 - t) * (1 - t) }
|
|
42
|
+
internal val tabTimingSpec = tween<Float>(durationMillis = 200, easing = inOutQuad)
|
|
43
|
+
|
|
44
|
+
internal val LocalBottomTabFocused = staticCompositionLocalOf { true }
|
|
45
|
+
|
|
46
|
+
private val Hidden = Modifier.layout { measurable, constraints ->
|
|
47
|
+
val placeable = measurable.measure(constraints)
|
|
48
|
+
layout(placeable.width, placeable.height) {}
|
|
49
|
+
}
|
|
32
50
|
|
|
33
51
|
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
34
52
|
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
@@ -52,10 +70,8 @@ fun BottomTab(
|
|
|
52
70
|
) {
|
|
53
71
|
val navigation = LocalNavigation.current
|
|
54
72
|
val navigator = LocalNavigator.current
|
|
55
|
-
val
|
|
56
|
-
val
|
|
57
|
-
"option${items.indexOfFirst { it.name == initialRouteName }.coerceAtLeast(0)}"
|
|
58
|
-
}
|
|
73
|
+
val maxApi = LocalMaxApi.current
|
|
74
|
+
val startIndex = remember { items.indexOfFirst { it.name == initialRouteName }.coerceAtLeast(0) }
|
|
59
75
|
|
|
60
76
|
bottomTabOptionItems = items.mapIndexed { index, item ->
|
|
61
77
|
item.options ?: NavigationOptions()
|
|
@@ -70,14 +86,34 @@ fun BottomTab(
|
|
|
70
86
|
)
|
|
71
87
|
}
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
val
|
|
76
|
-
val
|
|
89
|
+
var selectedIndex by rememberSaveable { mutableIntStateOf(startIndex) }
|
|
90
|
+
var loadedTabs by rememberSaveable { mutableStateOf(listOf(startIndex)) }
|
|
91
|
+
val tabStateHolder = rememberSaveableStateHolder()
|
|
92
|
+
val selectTab: (Int) -> Unit = { index ->
|
|
93
|
+
if (index !in loadedTabs) loadedTabs = loadedTabs + index
|
|
94
|
+
selectedIndex = index
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
val onFirstTab = selectedIndex == 0
|
|
98
|
+
val isFirstTab = onFirstTab || !backToInitialTab
|
|
99
|
+
val backToFirstTab = { selectTab(0) }
|
|
100
|
+
|
|
101
|
+
var lastFocusedIndex by rememberSaveable { mutableStateOf<Int?>(null) }
|
|
102
|
+
val tabProgress = remember { mutableMapOf<Int, Animatable<Float, AnimationVector1D>>() }
|
|
103
|
+
fun progressOf(index: Int) = tabProgress.getOrPut(index) {
|
|
104
|
+
Animatable(if (index == lastFocusedIndex) 1f else 0f)
|
|
105
|
+
}
|
|
106
|
+
LaunchedEffect(selectedIndex) {
|
|
107
|
+
lastFocusedIndex = selectedIndex
|
|
108
|
+
tabProgress.forEach { (index, progress) ->
|
|
109
|
+
if (index != selectedIndex) launch { progress.animateTo(0f, tabTimingSpec) }
|
|
110
|
+
}
|
|
111
|
+
progressOf(selectedIndex).animateTo(1f, tabTimingSpec)
|
|
112
|
+
}
|
|
77
113
|
|
|
78
114
|
DisposableEffect(isFirstTab) {
|
|
79
115
|
reportFloatingArrowBack(!isFirstTab)
|
|
80
|
-
navigator.tabBackHandler = if (isFirstTab) null else ({
|
|
116
|
+
navigator.tabBackHandler = if (isFirstTab) null else ({ backToFirstTab() })
|
|
81
117
|
// both live outside this composition
|
|
82
118
|
onDispose {
|
|
83
119
|
reportFloatingArrowBack(false)
|
|
@@ -88,75 +124,56 @@ fun BottomTab(
|
|
|
88
124
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
89
125
|
Box(modifier = Modifier
|
|
90
126
|
.fillMaxSize()
|
|
127
|
+
.background(AppTheme.current.colors.background.default)
|
|
91
128
|
) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
exitTransition = {
|
|
107
|
-
fadeOut(animationSpec = tween(200)) +
|
|
108
|
-
scaleOut(
|
|
109
|
-
targetScale = 0.97f,
|
|
110
|
-
animationSpec = tween(200)
|
|
111
|
-
)
|
|
112
|
-
},
|
|
113
|
-
popEnterTransition = {
|
|
114
|
-
fadeIn(animationSpec = tween(200)) +
|
|
115
|
-
scaleIn(
|
|
116
|
-
initialScale = 0.97f,
|
|
117
|
-
animationSpec = tween(200)
|
|
118
|
-
)
|
|
119
|
-
},
|
|
120
|
-
popExitTransition = {
|
|
121
|
-
fadeOut(animationSpec = tween(200)) +
|
|
122
|
-
scaleOut(
|
|
123
|
-
targetScale = 0.97f,
|
|
124
|
-
animationSpec = tween(200)
|
|
125
|
-
)
|
|
126
|
-
}
|
|
129
|
+
loadedTabs.forEach { index ->
|
|
130
|
+
val item = items.getOrNull(index) ?: return@forEach
|
|
131
|
+
val focused = index == selectedIndex
|
|
132
|
+
val progress = progressOf(index)
|
|
133
|
+
key(index) {
|
|
134
|
+
Box(
|
|
135
|
+
Modifier
|
|
136
|
+
.fillMaxSize()
|
|
137
|
+
.zIndex(if (focused) 0f else -1f)
|
|
138
|
+
.then(if (focused) Modifier.graphicsLayer {
|
|
139
|
+
alpha = 0.3f + 0.7f * progress.value
|
|
140
|
+
scaleX = 0.97f + 0.03f * progress.value
|
|
141
|
+
scaleY = scaleX
|
|
142
|
+
} else Hidden)
|
|
127
143
|
) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
CompositionLocalProvider(LocalBottomTabFocused provides focused) {
|
|
145
|
+
tabStateHolder.SaveableStateProvider(index) {
|
|
146
|
+
StackScreen(
|
|
147
|
+
content = item.screen,
|
|
148
|
+
navigationOptions = getBottomTabOption(index),
|
|
149
|
+
bottomTabIndex = index,
|
|
150
|
+
onBackHandler = {
|
|
151
|
+
if (backToInitialTab && index != 0) {
|
|
152
|
+
backToFirstTab()
|
|
153
|
+
} else {
|
|
154
|
+
navigator.pop()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
)
|
|
140
158
|
}
|
|
141
|
-
|
|
159
|
+
}
|
|
142
160
|
}
|
|
143
161
|
}
|
|
144
162
|
}
|
|
145
163
|
}
|
|
146
|
-
BackHandler(enabled = !
|
|
147
|
-
if (backToInitialTab)
|
|
164
|
+
BackHandler(enabled = !onFirstTab) {
|
|
165
|
+
if (backToInitialTab) backToFirstTab() else navigator.pop()
|
|
148
166
|
}
|
|
149
167
|
Column {
|
|
150
168
|
BottomTabBar(
|
|
151
169
|
items = items,
|
|
152
170
|
floatingButton = floatingButton,
|
|
153
|
-
|
|
171
|
+
selectedIndex = selectedIndex,
|
|
154
172
|
onTabSelected = { index ->
|
|
173
|
+
// RN parity: every tab press (focused one included) ticks a light haptic.
|
|
174
|
+
runCatching { maxApi?.triggerEventVibration("light", callback = null) }
|
|
155
175
|
val switchTab = {
|
|
156
|
-
|
|
157
|
-
if (navController.currentBackStackEntry?.destination?.route != targetRoute) {
|
|
158
|
-
navController.navigate(targetRoute)
|
|
159
|
-
}
|
|
176
|
+
if (index != selectedIndex) selectTab(index)
|
|
160
177
|
}
|
|
161
178
|
onTabPress?.invoke(index, switchTab) ?: switchTab()
|
|
162
179
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
package vn.momo.kits.navigation.bottomtab
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.core.
|
|
4
|
-
import androidx.compose.animation.core.animateDpAsState
|
|
5
|
-
import androidx.compose.animation.core.tween
|
|
3
|
+
import androidx.compose.animation.core.Animatable
|
|
6
4
|
import androidx.compose.foundation.background
|
|
7
5
|
import androidx.compose.foundation.border
|
|
8
6
|
import androidx.compose.foundation.layout.*
|
|
9
7
|
import androidx.compose.foundation.shape.CircleShape
|
|
10
8
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
11
9
|
import androidx.compose.runtime.Composable
|
|
10
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
12
11
|
import androidx.compose.runtime.getValue
|
|
12
|
+
import androidx.compose.runtime.mutableIntStateOf
|
|
13
|
+
import androidx.compose.runtime.remember
|
|
14
|
+
import androidx.compose.runtime.saveable.rememberSaveable
|
|
15
|
+
import androidx.compose.runtime.setValue
|
|
13
16
|
import androidx.compose.ui.Alignment
|
|
14
17
|
import androidx.compose.ui.Modifier
|
|
15
18
|
import androidx.compose.ui.draw.clip
|
|
@@ -17,18 +20,17 @@ import androidx.compose.ui.graphics.Brush
|
|
|
17
20
|
import androidx.compose.ui.graphics.Color
|
|
18
21
|
import androidx.compose.ui.text.style.TextAlign
|
|
19
22
|
import androidx.compose.ui.text.style.TextOverflow
|
|
23
|
+
import androidx.compose.ui.unit.Dp
|
|
24
|
+
import androidx.compose.ui.unit.IntOffset
|
|
20
25
|
import androidx.compose.ui.unit.dp
|
|
21
|
-
import androidx.navigation.NavController
|
|
22
|
-
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
23
26
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
24
27
|
import vn.momo.kits.components.*
|
|
25
28
|
import vn.momo.kits.const.*
|
|
26
29
|
import vn.momo.kits.modifier.InternalApi
|
|
27
30
|
import vn.momo.kits.modifier.conditional
|
|
28
|
-
import vn.momo.kits.modifier.
|
|
31
|
+
import vn.momo.kits.modifier.activeOpacityClickable
|
|
29
32
|
import vn.momo.kits.platform.getScreenDimensions
|
|
30
33
|
|
|
31
|
-
internal val floatingButtonWidth = 75.dp
|
|
32
34
|
@InternalApi
|
|
33
35
|
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
34
36
|
|
|
@@ -36,28 +38,24 @@ const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
|
36
38
|
internal fun BottomTabBar(
|
|
37
39
|
items: List<BottomTabItem>,
|
|
38
40
|
floatingButton: BottomTabFloatingButton? = null,
|
|
39
|
-
|
|
41
|
+
selectedIndex: Int,
|
|
40
42
|
onTabSelected: (Int) -> Unit,
|
|
41
43
|
) {
|
|
42
|
-
val currentRoute = navController.currentBackStackEntryAsState().value?.destination?.route
|
|
43
|
-
val selectedIndex = items.indexOfFirst { "option${items.indexOf(it)}" == currentRoute }
|
|
44
44
|
|
|
45
45
|
val screenWidth = getScreenDimensions().width.dp
|
|
46
46
|
val mid = items.size / 2
|
|
47
47
|
|
|
48
|
-
val
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
screenWidth / items.size
|
|
52
|
-
}
|
|
53
|
-
val adjustSize = if(floatingButton != null && selectedIndex >= mid) floatingButtonWidth else 0.dp
|
|
54
|
-
val targetOffset = tabWidth * selectedIndex + tabWidth / 2 - screenWidth / 2 + adjustSize
|
|
48
|
+
val floating = floatingButton?.takeIf { items.size % 2 == 0 }
|
|
49
|
+
val slotWidth = screenWidth / (items.size + if (floating != null) 1 else 0)
|
|
50
|
+
fun slotOf(index: Int) = if (floating != null && index >= mid) index + 1 else index
|
|
55
51
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
var indicatorSlot by rememberSaveable { mutableIntStateOf(0) }
|
|
53
|
+
val indicatorX = remember { Animatable(indicatorSlot.toFloat()) }
|
|
54
|
+
LaunchedEffect(selectedIndex) {
|
|
55
|
+
val target = slotOf(selectedIndex)
|
|
56
|
+
indicatorSlot = target
|
|
57
|
+
indicatorX.animateTo(target.toFloat(), tabTimingSpec)
|
|
58
|
+
}
|
|
61
59
|
|
|
62
60
|
Box(
|
|
63
61
|
contentAlignment = Alignment.BottomCenter
|
|
@@ -72,17 +70,17 @@ internal fun BottomTabBar(
|
|
|
72
70
|
},
|
|
73
71
|
horizontalArrangement = Arrangement.SpaceAround,
|
|
74
72
|
) {
|
|
75
|
-
if (
|
|
73
|
+
if (floating == null) {
|
|
76
74
|
RenderTabBarItem(items, 0, items.size, selectedIndex, onTabSelected)
|
|
77
75
|
} else {
|
|
78
76
|
RenderTabBarItem(items, 0, mid, selectedIndex, onTabSelected)
|
|
79
|
-
Spacer(modifier = Modifier.width(
|
|
77
|
+
Spacer(modifier = Modifier.width(slotWidth))
|
|
80
78
|
RenderTabBarItem(items, mid, items.size, selectedIndex, onTabSelected)
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
Box(modifier = Modifier
|
|
85
|
-
.offset(
|
|
83
|
+
.offset { IntOffset(((slotWidth * (indicatorX.value + 0.5f)) - screenWidth / 2).roundToPx(), (-BOTTOM_TAB_BAR_HEIGHT + 2).dp.roundToPx()) }
|
|
86
84
|
.height(2.dp)
|
|
87
85
|
.width(44.dp)
|
|
88
86
|
.background(
|
|
@@ -101,7 +99,7 @@ internal fun BottomTabBar(
|
|
|
101
99
|
)
|
|
102
100
|
)
|
|
103
101
|
)
|
|
104
|
-
|
|
102
|
+
floating?.let { FloatingButton(it, slotWidth) }
|
|
105
103
|
}
|
|
106
104
|
}
|
|
107
105
|
|
|
@@ -137,7 +135,7 @@ internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> U
|
|
|
137
135
|
.conditional(IsShowBaseLineDebug) {
|
|
138
136
|
border(1.dp, Colors.blue_03)
|
|
139
137
|
}
|
|
140
|
-
.
|
|
138
|
+
.activeOpacityClickable {
|
|
141
139
|
onClick()
|
|
142
140
|
},
|
|
143
141
|
contentAlignment = Alignment.BottomStart
|
|
@@ -145,10 +143,7 @@ internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> U
|
|
|
145
143
|
Column(
|
|
146
144
|
modifier = Modifier
|
|
147
145
|
.fillMaxSize()
|
|
148
|
-
.padding(horizontal = Spacing.S, vertical = Spacing.S)
|
|
149
|
-
.noFeedbackClickable {
|
|
150
|
-
onClick()
|
|
151
|
-
},
|
|
146
|
+
.padding(horizontal = Spacing.S, vertical = Spacing.S),
|
|
152
147
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
153
148
|
verticalArrangement = Arrangement.Center
|
|
154
149
|
) {
|
|
@@ -177,15 +172,15 @@ internal fun TabBarItem(item: BottomTabItem, selected: Boolean, onClick: () -> U
|
|
|
177
172
|
}
|
|
178
173
|
|
|
179
174
|
@Composable
|
|
180
|
-
internal fun FloatingButton(data: BottomTabFloatingButton) {
|
|
175
|
+
internal fun FloatingButton(data: BottomTabFloatingButton, width: Dp) {
|
|
181
176
|
Column(
|
|
182
177
|
modifier = Modifier
|
|
183
|
-
.width(
|
|
178
|
+
.width(width)
|
|
184
179
|
.padding(horizontal = Spacing.XXS, vertical = Spacing.S)
|
|
185
180
|
.conditional(IsShowBaseLineDebug) {
|
|
186
181
|
border(1.dp, Colors.blue_03)
|
|
187
182
|
}
|
|
188
|
-
.
|
|
183
|
+
.activeOpacityClickable {
|
|
189
184
|
data.onPress()
|
|
190
185
|
},
|
|
191
186
|
verticalArrangement = Arrangement.Bottom,
|
package/gradle.properties
CHANGED
package/ios/native-kits.podspec
CHANGED