refactor: make TabPosition opened and use TabRow to manage TabIndicator

This commit is contained in:
2023-11-28 09:39:14 +08:00
parent 65e01c2e51
commit c6b72b6501

View File

@@ -19,7 +19,7 @@
*
* This file is created by fankes on 2023/11/9.
*/
@file:Suppress("unused")
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package com.highcapable.flexiui.component
@@ -102,25 +102,7 @@ fun TabRow(
modifier: Modifier = Modifier,
colors: TabColors = Tab.colors,
style: TabStyle = Tab.style,
tabs: @Composable () -> Unit
) {
TabRow(
selectedTabIndex = selectedTabIndex,
modifier = modifier,
colors = colors,
style = style,
pagerState = null,
tabs = tabs
)
}
@Composable
fun TabRow(
selectedTabIndex: Int = 0,
modifier: Modifier = Modifier,
colors: TabColors = Tab.colors,
style: TabStyle = Tab.style,
pagerState: PagerState?,
indicator: @Composable TabRow.() -> Unit = { TabIndicator(modifier = Modifier.tabIndicatorOffset()) },
tabs: @Composable () -> Unit
) {
TabStyleBox(modifier, colors, style) {
@@ -145,7 +127,7 @@ fun TabRow(
placeable.placeRelative(x = index * tabAverageWidth, y = 0)
}
subcompose(TabSlots.Indicator) {
TabIndicator(selectedTabIndex, colors, style, pagerState, tabPositions)
indicator(TabRow(selectedTabIndex, colors, style, tabPositions))
}.forEach {
it.measure(Constraints.fixed(tabRowWidth, tabRowHeight)).placeRelative(x = 0, y = 0)
}
@@ -161,27 +143,7 @@ fun ScrollableTabRow(
colors: TabColors = Tab.colors,
style: TabStyle = Tab.style,
scrollState: ScrollState = rememberScrollState(),
tabs: @Composable () -> Unit
) {
ScrollableTabRow(
selectedTabIndex = selectedTabIndex,
modifier = modifier,
colors = colors,
style = style,
pagerState = null,
scrollState = scrollState,
tabs = tabs
)
}
@Composable
fun ScrollableTabRow(
selectedTabIndex: Int = 0,
modifier: Modifier = Modifier,
colors: TabColors = Tab.colors,
style: TabStyle = Tab.style,
pagerState: PagerState?,
scrollState: ScrollState = rememberScrollState(),
indicator: @Composable TabRow.() -> Unit = { TabIndicator(modifier = Modifier.tabIndicatorOffset()) },
tabs: @Composable () -> Unit
) {
TabStyleBox(modifier, colors, style) {
@@ -214,7 +176,7 @@ fun ScrollableTabRow(
tabLeft += placeables.width
}
subcompose(TabSlots.Indicator) {
TabIndicator(selectedTabIndex, colors, style, pagerState, tabPositions)
indicator(TabRow(selectedTabIndex, colors, style, tabPositions))
}.forEach {
it.measure(Constraints.fixed(layoutWidth, layoutHeight)).placeRelative(x = 0, y = 0)
}
@@ -271,23 +233,6 @@ fun Tab(
}
}
@Composable
private fun TabIndicator(
selectedTabIndex: Int,
colors: TabColors,
style: TabStyle,
pagerState: PagerState?,
tabPositions: List<TabPosition>
) {
val indicatorModifier = pagerState?.let { Modifier.pagerTabIndicatorOffset(it, tabPositions, style.indicatorWidth) }
?: Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex], style.indicatorWidth)
Box(
modifier = Modifier.then(indicatorModifier)
.height(style.indicatorHeight)
.background(colors.indicatorColor, style.indicatorShape)
)
}
@Composable
private fun TabStyleBox(
modifier: Modifier,
@@ -311,9 +256,35 @@ private fun rememberScrollableTabData(scrollState: ScrollState): ScrollableTabDa
return remember(scrollState, coroutineScope) { ScrollableTabData(scrollState, coroutineScope) }
}
private fun Modifier.tabIndicatorOffset(
currentTabPosition: TabPosition,
indicatorWidth: Dp
@Immutable
data class TabPosition(val left: Dp, val width: Dp, val tabWidth: Dp) {
val right get() = left + width
fun calculateCenter(currentWidth: Dp) = left + width / 2 - currentWidth / 2
}
@Stable
class TabRow internal constructor(
val selectedTabIndex: Int,
val colors: TabColors,
val style: TabStyle,
val tabPositions: List<TabPosition>
) {
@Composable
fun TabIndicator(
modifier: Modifier = Modifier,
color: Color = colors.indicatorColor,
height: Dp = style.indicatorHeight,
shape: Shape = style.indicatorShape
) {
Box(modifier.height(height).background(color, shape))
}
fun Modifier.tabIndicatorOffset(
currentTabPosition: TabPosition = tabPositions[selectedTabIndex],
indicatorWidth: Dp = style.indicatorWidth
) = composed(
inspectorInfo = debugInspectorInfo {
name = "tabIndicatorOffset"
@@ -336,10 +307,10 @@ private fun Modifier.tabIndicatorOffset(
.width(animatedWidh)
}
private fun Modifier.pagerTabIndicatorOffset(
fun Modifier.pagerTabIndicatorOffset(
pagerState: PagerState,
tabPositions: List<TabPosition>,
indicatorWidth: Dp
tabPositions: List<TabPosition> = this@TabRow.tabPositions,
indicatorWidth: Dp = style.indicatorWidth
) = composed(
inspectorInfo = debugInspectorInfo {
name = "pagerTabIndicatorOffset"
@@ -387,6 +358,7 @@ private fun Modifier.pagerTabIndicatorOffset(
layout(measureWidth, measureHeight) { placeable.placeRelative(movableOffsetX, offsetY) }
}
}
}
@Stable
private class ScrollableTabData(private val scrollState: ScrollState, private val coroutineScope: CoroutineScope) {
@@ -433,14 +405,6 @@ private class ScrollableTabData(private val scrollState: ScrollState, private va
}
}
@Immutable
private data class TabPosition(val left: Dp, val width: Dp, val tabWidth: Dp) {
val right get() = left + width
fun calculateCenter(currentWidth: Dp) = left + width / 2 - currentWidth / 2
}
@Stable
private enum class TabSlots { Tabs, TabsAverage, Indicator }