Skip to content

Commit 6bb30bf

Browse files
author
Bořek Leikep
committed
Added extraContent slot to TopAppBarLarge.
1 parent 2e48396 commit 6bb30bf

11 files changed

+122
-29
lines changed

catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreen.kt

+21-10
Original file line numberDiff line numberDiff line change
@@ -33,34 +33,37 @@ import kotlinx.serialization.Serializable
3333

3434
sealed interface TopAppBarDestination : Destination {
3535
@Serializable
36-
object Home : TopAppBarDestination
36+
data object Home : TopAppBarDestination
3737

3838
@Serializable
39-
object Normal : TopAppBarDestination
39+
data object Normal : TopAppBarDestination
4040

4141
@Serializable
42-
object NormalScrollable : TopAppBarDestination
42+
data object NormalScrollable : TopAppBarDestination
4343

4444
@Serializable
45-
object NormalWithTabs : TopAppBarDestination
45+
data object NormalWithTabs : TopAppBarDestination
4646

4747
@Serializable
48-
object NormalWithFilters : TopAppBarDestination
48+
data object NormalWithFilters : TopAppBarDestination
4949

5050
@Serializable
51-
object Large : TopAppBarDestination
51+
data object Large : TopAppBarDestination
5252

5353
@Serializable
54-
object LargeScrollable : TopAppBarDestination
54+
data object LargeScrollable : TopAppBarDestination
5555

5656
@Serializable
57-
object LargeScrollableElevated : TopAppBarDestination
57+
data object LargeScrollableElevated : TopAppBarDestination
5858

5959
@Serializable
60-
object LargeCustomContent : TopAppBarDestination
60+
data object LargeWithTabs : TopAppBarDestination
6161

6262
@Serializable
63-
object LargePullRefresh : TopAppBarDestination
63+
data object LargeCustomContent : TopAppBarDestination
64+
65+
@Serializable
66+
data object LargePullRefresh : TopAppBarDestination
6467
}
6568

6669
@ExperimentalSerializationApi
@@ -94,6 +97,9 @@ internal inline fun <reified T : Destination> NavGraphBuilder.topAppBarNavigatio
9497
composable<TopAppBarDestination.LargeScrollableElevated> {
9598
TopAppBarLargeScrollableElevatedScreen(navController::navigateUp)
9699
}
100+
composable<TopAppBarDestination.LargeWithTabs> {
101+
TopAppBarLargeWithTabsScreen(navController::navigateUp)
102+
}
97103
composable<TopAppBarDestination.LargeCustomContent> {
98104
TopAppBarLargeCustomContentScreen(navController::navigateUp)
99105
}
@@ -166,6 +172,11 @@ internal fun TopAppBarScreenInner(
166172
) {
167173
Text("Scrollable Elevated")
168174
}
175+
ButtonSecondary(
176+
onClick = { onSelect(TopAppBarDestination.LargeWithTabs) },
177+
) {
178+
Text("With Tabs")
179+
}
169180
ButtonSecondary(
170181
onClick = { onSelect(TopAppBarDestination.LargeCustomContent) },
171182
) {

catalog/src/main/java/kiwi/orbit/compose/catalog/screens/TopAppBarScreensLarge.kt

+35
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import kiwi.orbit.compose.ui.OrbitTheme
3333
import kiwi.orbit.compose.ui.controls.Icon
3434
import kiwi.orbit.compose.ui.controls.IconButton
3535
import kiwi.orbit.compose.ui.controls.Scaffold
36+
import kiwi.orbit.compose.ui.controls.Tab
37+
import kiwi.orbit.compose.ui.controls.TabRow
3638
import kiwi.orbit.compose.ui.controls.Text
3739
import kiwi.orbit.compose.ui.controls.TopAppBarLarge
3840
import kiwi.orbit.compose.ui.controls.TopAppBarScrollBehavior
@@ -100,6 +102,39 @@ internal fun TopAppBarLargeScrollableElevatedScreen(
100102
)
101103
}
102104

105+
@Composable
106+
internal fun TopAppBarLargeWithTabsScreen(
107+
onNavigateUp: () -> Unit,
108+
) {
109+
val scrollBehavior = TopAppBarScrollBehavior.exitUntilCollapsed()
110+
Scaffold(
111+
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
112+
topBar = {
113+
TopAppBarLarge(
114+
title = { Text("With Tabs") },
115+
onNavigateUp = onNavigateUp,
116+
extraContent = {
117+
var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) }
118+
TabRow(selectedTabIndex = selectedTabIndex) {
119+
Tab(
120+
selected = selectedTabIndex == 0,
121+
onClick = { selectedTabIndex = 0 },
122+
text = { Text("Normal") },
123+
)
124+
Tab(
125+
selected = selectedTabIndex == 1,
126+
onClick = { selectedTabIndex = 1 },
127+
text = { Text("Inline") },
128+
)
129+
}
130+
},
131+
scrollBehavior = scrollBehavior,
132+
)
133+
},
134+
content = { CustomContentPlaceholder(it) },
135+
)
136+
}
137+
103138
@Composable
104139
internal fun TopAppBarLargeCustomContentScreen(
105140
onNavigateUp: () -> Unit,

ui/detekt-baseline-debug.xml

+1-7
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,20 @@
33
<ManuallySuppressedIssues/>
44
<CurrentIssues>
55
<ID>CyclomaticComplexMethod:Checkbox.kt$@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable public fun Checkbox( checked: Boolean, onCheckedChange: (() -> Unit)?, modifier: Modifier = Modifier, enabled: Boolean = true, isError: Boolean = false, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, )</ID>
6-
<ID>CyclomaticComplexMethod:Scaffold.kt$@OptIn(ExperimentalLayoutApi::class) @Composable private fun ScaffoldLayout( topBar: @Composable () -> Unit, toast: @Composable () -> Unit, action: @Composable () -> Unit, content: @Composable (contentPadding: PaddingValues) -> Unit, contentWindowInsets: WindowInsets, )</ID>
7-
<ID>CyclomaticComplexMethod:Seat.kt$@Composable private fun ColumnScope.Seat( selected: Boolean, enabled: Boolean, isExtraLegroom: Boolean, content: @Composable () -> Unit, )</ID>
86
<ID>CyclomaticComplexMethod:Slider.kt$@Composable private fun Track(enabled: Boolean, sliderPositions: SliderPositions)</ID>
9-
<ID>CyclomaticComplexMethod:TextField.kt$@Suppress("LongParameterList") @Composable internal fun TextField( value: String, onValueChange: (String) -> Unit, enabled: Boolean, readOnly: Boolean, label: @Composable (() -> Unit)?, error: @Composable (() -> Unit)?, info: @Composable (() -> Unit)?, additionalContent: @Composable (() -> Unit)?, placeholder: @Composable (() -> Unit)?, leadingIcon: @Composable (() -> Unit)?, onLeadingIconClick: (() -> Unit)?, trailingIcon: @Composable (() -> Unit)?, onTrailingIconClick: (() -> Unit)?, keyboardOptions: KeyboardOptions, keyboardActions: KeyboardActions, singleLine: Boolean, maxLines: Int, minLines: Int, visualTransformation: VisualTransformation, interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, )</ID>
107
<ID>ForbiddenComment:SelectField.kt$// TODO:</ID>
118
<ID>ForbiddenComment:Typography.kt$Typography$// TODO: remove data class to allow maintain better binary compatibility</ID>
129
<ID>FunctionNaming:SwipeableV2.kt$SwipeableV2Defaults$internal fun &lt;T> ReconcileAnimationOnAnchorChangeHandler( state: SwipeableV2State&lt;T>, animate: (target: T, velocity: Float) -> Unit, snap: (target: T) -> Unit )</ID>
1310
<ID>FunctionNaming:SwipeableV2.kt$SwipeableV2State.Companion$fun &lt;T : Any> Saver( animationSpec: AnimationSpec&lt;Float>, confirmValueChange: (T) -> Boolean, positionalThreshold: Density.(distance: Float) -> Float, velocityThreshold: Dp )</ID>
14-
<ID>LongMethod:Alert.kt$@Composable private fun Alert( icon: Painter?, title: @Composable ColumnScope.() -> Unit, actions: @Composable () -> Unit, content: @Composable ColumnScope.() -> Unit, suppressed: Boolean, modifier: Modifier = Modifier, )</ID>
1511
<ID>LongMethod:Checkbox.kt$@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable public fun Checkbox( checked: Boolean, onCheckedChange: (() -> Unit)?, modifier: Modifier = Modifier, enabled: Boolean = true, isError: Boolean = false, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, )</ID>
1612
<ID>LongMethod:FieldContent.kt$FieldContentMeasurePolicy$override fun MeasureScope.measure( measurables: List&lt;Measurable>, constraints: Constraints, ): MeasureResult</ID>
1713
<ID>LongMethod:ListChoice.kt$@Composable private fun ListChoicePrimitive( onClick: (() -> Unit)?, icon: @Composable () -> Unit, description: @Composable () -> Unit, trailingIcon: @Composable () -> Unit, withSeparator: Boolean, interactionSource: MutableInteractionSource, title: @Composable () -> Unit, modifier: Modifier = Modifier, )</ID>
1814
<ID>LongMethod:SegmentedSwitch.kt$@Composable public fun SegmentedSwitch( onOptionClick: (selectedIndex: Int) -> Unit, options: List&lt;@Composable () -> Unit>, selectedIndex: Int?, modifier: Modifier = Modifier, label: @Composable () -> Unit = {}, error: @Composable (() -> Unit)? = null, info: @Composable (() -> Unit)? = null, )</ID>
1915
<ID>LongMethod:SelectField.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable public fun &lt;T> SelectField( value: String, options: List&lt;T>, onOptionSelect: (T) -> Unit, modifier: Modifier = Modifier, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, label: @Composable (() -> Unit)? = null, error: @Composable (() -> Unit)? = null, info: @Composable (() -> Unit)? = null, placeholder: @Composable (() -> Unit)? = null, leadingIcon: @Composable (() -> Unit)? = null, singleLine: Boolean = true, maxLines: Int = if (singleLine) 1 else Int.MAX_VALUE, minLines: Int = 1, optionContent: @Composable RowScope.(option: T) -> Unit, )</ID>
2016
<ID>LongMethod:Slider.kt$@Composable private fun Track(enabled: Boolean, sliderPositions: SliderPositions)</ID>
21-
<ID>LongMethod:Switch.kt$@Composable private fun BoxScope.SwitchImpl( checked: Boolean, enabled: Boolean, state: SwipeableV2State&lt;Boolean>, interactionSource: InteractionSource, )</ID>
22-
<ID>LongMethod:TextField.kt$@Suppress("LongParameterList") @Composable internal fun TextField( value: String, onValueChange: (String) -> Unit, enabled: Boolean, readOnly: Boolean, label: @Composable (() -> Unit)?, error: @Composable (() -> Unit)?, info: @Composable (() -> Unit)?, additionalContent: @Composable (() -> Unit)?, placeholder: @Composable (() -> Unit)?, leadingIcon: @Composable (() -> Unit)?, onLeadingIconClick: (() -> Unit)?, trailingIcon: @Composable (() -> Unit)?, onTrailingIconClick: (() -> Unit)?, keyboardOptions: KeyboardOptions, keyboardActions: KeyboardActions, singleLine: Boolean, maxLines: Int, minLines: Int, visualTransformation: VisualTransformation, interactionSource: MutableInteractionSource, modifier: Modifier = Modifier, )</ID>
2317
<ID>LongMethod:Toast.kt$private fun Modifier.toastGesturesDetector( onPause: () -> Unit, onResume: () -> Unit, onDismissed: () -> Unit, ): Modifier</ID>
2418
<ID>LongMethod:TopAppBar.kt$@Composable internal fun TopAppBarLayout( title: @Composable () -> Unit, titleAlpha: Float, hideTitleSemantics: Boolean, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, modifier: Modifier = Modifier, )</ID>
25-
<ID>LongMethod:TopAppBarLarge.kt$@Composable private fun TwoRowsTopAppBar( title: @Composable () -> Unit, largeTitle: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, largeElevated: Boolean, elevation: Dp, scrollBehavior: TopAppBarScrollBehavior?, modifier: Modifier = Modifier, )</ID>
19+
<ID>LongMethod:TopAppBarLarge.kt$@Composable private fun TwoRowsTopAppBar( title: @Composable () -> Unit, largeTitle: @Composable () -> Unit, navigationIcon: @Composable () -> Unit, actions: @Composable () -> Unit, extraContent: @Composable () -> Unit, largeElevated: Boolean, elevation: Dp, scrollBehavior: TopAppBarScrollBehavior?, modifier: Modifier = Modifier, )</ID>
2620
<ID>MatchingDeclarationName:Toast.kt$ToastData</ID>
2721
<ID>MatchingDeclarationName:ToastHost.kt$ToastHostState</ID>
2822
<ID>NestedBlockDepth:SwipeableV2.kt$SwipeableV2State$private fun computeTarget( offset: Float, currentValue: T, velocity: Float ): T</ID>

ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBar.kt

+23
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import androidx.compose.foundation.layout.statusBarsPadding
1717
import androidx.compose.foundation.layout.windowInsetsPadding
1818
import androidx.compose.runtime.Composable
1919
import androidx.compose.runtime.CompositionLocalProvider
20+
import androidx.compose.runtime.getValue
21+
import androidx.compose.runtime.mutableIntStateOf
22+
import androidx.compose.runtime.saveable.rememberSaveable
23+
import androidx.compose.runtime.setValue
2024
import androidx.compose.ui.Alignment
2125
import androidx.compose.ui.Modifier
2226
import androidx.compose.ui.draw.alpha
@@ -289,5 +293,24 @@ internal fun TopAppBarPreview() {
289293
}
290294
},
291295
)
296+
TopAppBar(
297+
title = { Text("Title") },
298+
onNavigateUp = {},
299+
extraContent = {
300+
var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) }
301+
TabRow(selectedTabIndex = selectedTabIndex) {
302+
Tab(
303+
selected = selectedTabIndex == 0,
304+
onClick = { selectedTabIndex = 0 },
305+
text = { Text("Tab A") },
306+
)
307+
Tab(
308+
selected = selectedTabIndex == 1,
309+
onClick = { selectedTabIndex = 1 },
310+
text = { Text("Tab B") },
311+
)
312+
}
313+
},
314+
)
292315
}
293316
}

ui/src/androidMain/kotlin/kiwi/orbit/compose/ui/controls/TopAppBarLarge.kt

+30
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import androidx.compose.foundation.layout.padding
1515
import androidx.compose.foundation.layout.systemBars
1616
import androidx.compose.foundation.layout.windowInsetsPadding
1717
import androidx.compose.runtime.Composable
18+
import androidx.compose.runtime.getValue
19+
import androidx.compose.runtime.mutableIntStateOf
20+
import androidx.compose.runtime.saveable.rememberSaveable
21+
import androidx.compose.runtime.setValue
1822
import androidx.compose.ui.Alignment
1923
import androidx.compose.ui.Modifier
2024
import androidx.compose.ui.draw.alpha
@@ -43,6 +47,7 @@ public fun TopAppBarLarge(
4347
largeTitle: @Composable () -> Unit = title,
4448
navigationIcon: Painter = TopAppBarIcons.Back,
4549
actions: @Composable RowScope.() -> Unit = {},
50+
extraContent: @Composable () -> Unit = {},
4651
largeElevated: Boolean = true,
4752
elevation: Dp = TopAppBarElevation,
4853
scrollBehavior: TopAppBarScrollBehavior? = null,
@@ -62,6 +67,7 @@ public fun TopAppBarLarge(
6267
},
6368
largeTitle = largeTitle,
6469
actions = actions,
70+
extraContent = extraContent,
6571
largeElevated = largeElevated,
6672
elevation = elevation,
6773
scrollBehavior = scrollBehavior,
@@ -75,6 +81,7 @@ public fun TopAppBarLarge(
7581
navigationIcon: @Composable () -> Unit = {},
7682
largeTitle: @Composable () -> Unit = title,
7783
actions: @Composable RowScope.() -> Unit = {},
84+
extraContent: @Composable () -> Unit = {},
7885
largeElevated: Boolean = true,
7986
elevation: Dp = TopAppBarElevation,
8087
scrollBehavior: TopAppBarScrollBehavior? = null,
@@ -106,6 +113,7 @@ public fun TopAppBarLarge(
106113
content = actions,
107114
)
108115
},
116+
extraContent = extraContent,
109117
largeElevated = largeElevated,
110118
elevation = elevation,
111119
scrollBehavior = scrollBehavior,
@@ -119,6 +127,7 @@ private fun TwoRowsTopAppBar(
119127
largeTitle: @Composable () -> Unit,
120128
navigationIcon: @Composable () -> Unit,
121129
actions: @Composable () -> Unit,
130+
extraContent: @Composable () -> Unit,
122131
largeElevated: Boolean,
123132
elevation: Dp,
124133
scrollBehavior: TopAppBarScrollBehavior?,
@@ -177,6 +186,7 @@ private fun TwoRowsTopAppBar(
177186
hideTitleSemantics = hideBottomRowSemantics,
178187
modifier = Modifier,
179188
)
189+
extraContent()
180190
}
181191
}
182192
} else {
@@ -210,6 +220,7 @@ private fun TwoRowsTopAppBar(
210220
WindowInsets.systemBars.only(WindowInsetsSides.Horizontal),
211221
),
212222
)
223+
extraContent()
213224
}
214225
}
215226
}
@@ -257,5 +268,24 @@ internal fun TopAppBarLargePreview() {
257268
}
258269
},
259270
)
271+
TopAppBarLarge(
272+
title = { Text("Title") },
273+
onNavigateUp = {},
274+
extraContent = {
275+
var selectedTabIndex by rememberSaveable { mutableIntStateOf(0) }
276+
TabRow(selectedTabIndex = selectedTabIndex) {
277+
Tab(
278+
selected = selectedTabIndex == 0,
279+
onClick = { selectedTabIndex = 0 },
280+
text = { Text("Tab A") },
281+
)
282+
Tab(
283+
selected = selectedTabIndex == 1,
284+
onClick = { selectedTabIndex = 1 },
285+
text = { Text("Tab B") },
286+
)
287+
}
288+
},
289+
)
260290
}
261291
}
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)