From d0b14d6cd9daa7f28440526774e81f2a0d55b373 Mon Sep 17 00:00:00 2001 From: Flaringapp Date: Sat, 4 Apr 2026 21:30:38 +0300 Subject: [PATCH 1/5] Add scaffold body scope with resize modifier --- .../api/ComposeCollapsingTopBar.klib.api | 6 +- .../scaffold/CollapsingTopBarScaffold.kt | 85 ++++++++++++++++--- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/ComposeCollapsingTopBar/api/ComposeCollapsingTopBar.klib.api b/ComposeCollapsingTopBar/api/ComposeCollapsingTopBar.klib.api index 7e8d9ec..e7cc17c 100644 --- a/ComposeCollapsingTopBar/api/ComposeCollapsingTopBar.klib.api +++ b/ComposeCollapsingTopBar/api/ComposeCollapsingTopBar.klib.api @@ -35,6 +35,10 @@ abstract interface com.flaringapp.compose.topbar.nestedscroll/CollapsingTopBarNe open suspend fun (androidx.compose.foundation.gestures/ScrollableState).fling(androidx.compose.foundation.gestures/FlingBehavior, kotlin/Float): kotlin/Float // com.flaringapp.compose.topbar.nestedscroll/CollapsingTopBarNestedScrollHandler.fling|fling@androidx.compose.foundation.gestures.ScrollableState(androidx.compose.foundation.gestures.FlingBehavior;kotlin.Float){}[0] } +abstract interface com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldBodyScope { // com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldBodyScope|null[0] + abstract fun (androidx.compose.ui/Modifier).resizeWithCollapse(): androidx.compose.ui/Modifier // com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldBodyScope.resizeWithCollapse|resizeWithCollapse@androidx.compose.ui.Modifier(){}[0] +} + abstract interface com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapBehavior { // com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapBehavior|null[0] abstract suspend fun (com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapScope).snap(kotlin/Boolean) // com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapBehavior.snap|snap@com.flaringapp.compose.topbar.snap.CollapsingTopBarSnapScope(kotlin.Boolean){}[0] } @@ -332,7 +336,7 @@ final fun com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topb final fun com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollExpand_AtTop$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollExpand_AtTop$stableprop_getter|com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollExpand_AtTop$stableprop_getter(){}[0] final fun com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollSnap$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollSnap$stableprop_getter|com_flaringapp_compose_topbar_nestedscroll_CollapsingTopBarNestedScrollSnap$stableprop_getter(){}[0] final fun com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_MultiNestedScrollConnection$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.nestedscroll/com_flaringapp_compose_topbar_nestedscroll_MultiNestedScrollConnection$stableprop_getter|com_flaringapp_compose_topbar_nestedscroll_MultiNestedScrollConnection$stableprop_getter(){}[0] -final fun com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffold(com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldScrollMode, androidx.compose.ui/Modifier?, com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldState?, kotlin/Boolean, com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapBehavior?, androidx.compose.ui/Modifier?, kotlin/Boolean, kotlin/Function4, kotlin/Function2, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffold|CollapsingTopBarScaffold(com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffoldScrollMode;androidx.compose.ui.Modifier?;com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffoldState?;kotlin.Boolean;com.flaringapp.compose.topbar.snap.CollapsingTopBarSnapBehavior?;androidx.compose.ui.Modifier?;kotlin.Boolean;kotlin.Function4;kotlin.Function2;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] +final fun com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffold(com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldScrollMode, androidx.compose.ui/Modifier?, com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffoldState?, kotlin/Boolean, com.flaringapp.compose.topbar.snap/CollapsingTopBarSnapBehavior?, androidx.compose.ui/Modifier?, kotlin/Boolean, kotlin/Function4, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // com.flaringapp.compose.topbar.scaffold/CollapsingTopBarScaffold|CollapsingTopBarScaffold(com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffoldScrollMode;androidx.compose.ui.Modifier?;com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffoldState?;kotlin.Boolean;com.flaringapp.compose.topbar.snap.CollapsingTopBarSnapBehavior?;androidx.compose.ui.Modifier?;kotlin.Boolean;kotlin.Function4;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] final fun com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode$stableprop_getter|com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode$stableprop_getter(){}[0] final fun com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode_Exit$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode_Exit$stableprop_getter|com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldScrollMode_Exit$stableprop_getter(){}[0] final fun com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldState$stableprop_getter(): kotlin/Int // com.flaringapp.compose.topbar.scaffold/com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldState$stableprop_getter|com_flaringapp_compose_topbar_scaffold_CollapsingTopBarScaffoldState$stableprop_getter(){}[0] diff --git a/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt b/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt index fa4a984..6ae5fbd 100644 --- a/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt +++ b/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt @@ -16,8 +16,10 @@ package com.flaringapp.compose.topbar.scaffold +import androidx.compose.foundation.layout.LayoutScopeMarker import androidx.compose.foundation.layout.offset import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue @@ -26,6 +28,9 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.Layout +import androidx.compose.ui.layout.Measurable +import androidx.compose.ui.layout.ParentDataModifier +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.constrainHeight import androidx.compose.ui.unit.constrainWidth @@ -63,9 +68,12 @@ import kotlin.math.max * @param topBarClipToBounds the flag whether or not to automatically clip top bar content [topBar] * to the actual collapse height. * @param topBar the content of [CollapsingTopBar]. - * @param body the scrollable content under collapsing top bar. If you don't use any by default - * scrollable container (e.g. [androidx.compose.foundation.lazy.LazyList]), then make sure to - * apply custom [androidx.compose.foundation.verticalScroll] modifier. + * @param body the content under collapsing top bar. By default, direct body children are measured + * against collapsed top bar height to minimize remeasurement during collapse. Use + * [CollapsingTopBarScaffoldBodyScope.resizeWithCollapse] on direct body children that should + * resize with the current top bar height instead. If you don't use any by default scrollable + * container (e.g. [androidx.compose.foundation.lazy.LazyList]), then make sure to apply custom + * [androidx.compose.foundation.verticalScroll] modifier. * * @see CollapsingTopBar */ @@ -80,7 +88,7 @@ public fun CollapsingTopBarScaffold( topBarModifier: Modifier = Modifier, topBarClipToBounds: Boolean = true, topBar: @Composable CollapsingTopBarScope.(topBarState: CollapsingTopBarState) -> Unit, - body: @Composable () -> Unit, + body: @Composable CollapsingTopBarScaffoldBodyScope.() -> Unit, ) { LaunchedEffect(scrollMode.canExit) { if (!scrollMode.canExit) { @@ -125,7 +133,7 @@ public fun CollapsingTopBarScaffold( topBar(state.topBarState) } - body() + CollapsingTopBarScaffoldBodyScopeInstance.body() }, modifier = modifier .then( @@ -140,15 +148,26 @@ public fun CollapsingTopBarScaffold( val topBarPlaceable = measurables[0].measure(topBarConstraints) val bodyPlaceables = if (measurables.size > 1) { - val bodyHeight = (constraints.maxHeight - topBarMinHeightState).coerceAtLeast(0) - - val bodyConstraints = constraints.copy( + val collapsedBodyConstrains = constraints.copy( minWidth = 0, minHeight = 0, - maxHeight = bodyHeight, + maxHeight = (constraints.maxHeight - topBarMinHeightState).coerceAtLeast(0), + ) + val resizedBodyConstrains = collapsedBodyConstrains.copy( + maxHeight = (constraints.maxHeight - state.totalTopBarHeight.toInt()) + .coerceAtLeast(0), ) + val bodyMeasurables = measurables.subList(1, measurables.size) - bodyMeasurables.map { it.measure(bodyConstraints) } + bodyMeasurables.map { measurable -> + val nodeConstraints = if (measurable.bodyParentData?.resizeWithCollapse == true) { + resizedBodyConstrains + } else { + collapsedBodyConstrains + } + + measurable.measure(nodeConstraints) + } } else { emptyList() } @@ -175,3 +194,49 @@ public fun CollapsingTopBarScaffold( } } } + +/** + * Scope for direct body children of [CollapsingTopBarScaffold]. + */ +@LayoutScopeMarker +@Immutable +public interface CollapsingTopBarScaffoldBodyScope { + + /** + * Opt this direct scaffold body child into measurement against current visible top bar height + * instead of collapsed top bar height. + */ + public fun Modifier.resizeWithCollapse(): Modifier +} + +private object CollapsingTopBarScaffoldBodyScopeInstance : CollapsingTopBarScaffoldBodyScope { + + override fun Modifier.resizeWithCollapse(): Modifier { + return then(ResizeWithCollapseModifier()) + } +} + +private class ResizeWithCollapseModifier : CollapsingTopBarScaffoldBodyParentDataModifier() { + override fun modifyParentData(parentData: CollapsingTopBarScaffoldBodyParentData) { + parentData.resizeWithCollapse = true + } +} + +private abstract class CollapsingTopBarScaffoldBodyParentDataModifier : ParentDataModifier { + + override fun Density.modifyParentData(parentData: Any?): Any { + val data = parentData as? CollapsingTopBarScaffoldBodyParentData + ?: CollapsingTopBarScaffoldBodyParentData() + this@CollapsingTopBarScaffoldBodyParentDataModifier.modifyParentData(data) + return data + } + + protected abstract fun modifyParentData(parentData: CollapsingTopBarScaffoldBodyParentData) +} + +private data class CollapsingTopBarScaffoldBodyParentData( + var resizeWithCollapse: Boolean = false, +) + +private val Measurable.bodyParentData: CollapsingTopBarScaffoldBodyParentData? + get() = parentData as? CollapsingTopBarScaffoldBodyParentData From 0e01a07e0523f85a665a1793f7589eb822322ee9 Mon Sep 17 00:00:00 2001 From: Flaringapp Date: Sat, 4 Apr 2026 21:52:50 +0300 Subject: [PATCH 2/5] Update readme --- README.md | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 281f2d3..ba8a17c 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,10 @@ dependencyResolutionManagement { ## Usage -You need a scrollable content for the collapsing header to work. For the sake of optimization, this -library does something similar to `CoordinatorLayout`: instead of resizing a content as a top bar -collapses, the content is simply offset downward. That's why you need a `Scaffold`-like wrapper. +You need scrollable content for the collapsing header to work. For the sake of optimization, this +library does something similar to `CoordinatorLayout`: by default, body content is measured as if +the top bar were already collapsed, and then simply offset as the top bar expands and +collapses. That's why you need a `Scaffold`-like wrapper. ```kotlin CollapsingTopBarScaffold( @@ -63,6 +64,26 @@ CollapsingTopBarScaffold( ) ``` +In some cases you may want a direct body child to resize together with collapse instead of using +the default fixed measurement strategy. For those cases, `CollapsingTopBarScaffold()` exposes +`CollapsingTopBarScaffoldBodyScope.resizeWithCollapse()`: + +```kotlin +CollapsingTopBarScaffold( + scrollMode = CollapsingTopBarScaffoldScrollMode.collapse(expandAlways = false), + topBar = { + TopBarImage() + TopAppBar() + }, + body = { + ScrollableContent() + Overlay( + modifier = Modifier.resizeWithCollapse(), + ) + }, +) +``` + `CollapsingTopBarScaffold()` is flexible enough to cover a variety of use cases. However, there's some extra room for customization: you can use `CollapsingTopBar()` as the actual collapsing header, and implement your own mechanism to control header and content positioning. Feel free to take a From 09f7ca856b1595df89f25930de576c8987e5b6ff Mon Sep 17 00:00:00 2001 From: Flaringapp Date: Sat, 4 Apr 2026 22:19:51 +0300 Subject: [PATCH 3/5] Update documentation and readme with warnings --- .../topbar/scaffold/CollapsingTopBarScaffold.kt | 13 +++++++++---- README.md | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt b/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt index 6ae5fbd..a8737ee 100644 --- a/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt +++ b/ComposeCollapsingTopBar/src/commonMain/kotlin/com/flaringapp/compose/topbar/scaffold/CollapsingTopBarScaffold.kt @@ -70,10 +70,11 @@ import kotlin.math.max * @param topBar the content of [CollapsingTopBar]. * @param body the content under collapsing top bar. By default, direct body children are measured * against collapsed top bar height to minimize remeasurement during collapse. Use - * [CollapsingTopBarScaffoldBodyScope.resizeWithCollapse] on direct body children that should - * resize with the current top bar height instead. If you don't use any by default scrollable - * container (e.g. [androidx.compose.foundation.lazy.LazyList]), then make sure to apply custom - * [androidx.compose.foundation.verticalScroll] modifier. + * [CollapsingTopBarScaffoldBodyScope.resizeWithCollapse] only for direct body children that must + * resize with the current top bar height instead, such as lightweight overlays. It may increase + * remeasurement cost and is generally not recommended for scrollable content. If you don't use any + * by default scrollable container (e.g. [androidx.compose.foundation.lazy.LazyList]), then make + * sure to apply custom [androidx.compose.foundation.verticalScroll] modifier. * * @see CollapsingTopBar */ @@ -205,6 +206,10 @@ public interface CollapsingTopBarScaffoldBodyScope { /** * Opt this direct scaffold body child into measurement against current visible top bar height * instead of collapsed top bar height. + * + * This may increase remeasurement cost during collapse. Prefer the default scaffold body + * behavior unless this child must respond to the current visible top bar height, e.g. for a + * lightweight overlay. */ public fun Modifier.resizeWithCollapse(): Modifier } diff --git a/README.md b/README.md index ba8a17c..0aace9f 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,11 @@ CollapsingTopBarScaffold( ) ``` +Use `resizeWithCollapse()` as a targeted override, typically for lightweight direct children such +as overlays or panels that must track the currently visible body height. It may increase +remeasurement cost during collapse, so the default scaffold behavior remains the preferred choice +for scrollable content. + `CollapsingTopBarScaffold()` is flexible enough to cover a variety of use cases. However, there's some extra room for customization: you can use `CollapsingTopBar()` as the actual collapsing header, and implement your own mechanism to control header and content positioning. Feel free to take a From 500adb077dd233d54cdabd4b1b073e34272f13b0 Mon Sep 17 00:00:00 2001 From: Flaringapp Date: Sat, 4 Apr 2026 22:43:07 +0300 Subject: [PATCH 4/5] Add body resize sample --- .../samples/CollapsingTopBarSampleGroups.kt | 2 + .../ui/samples/advanced/BodyResizeSample.kt | 122 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt diff --git a/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/CollapsingTopBarSampleGroups.kt b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/CollapsingTopBarSampleGroups.kt index 9c40f24..e78476e 100644 --- a/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/CollapsingTopBarSampleGroups.kt +++ b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/CollapsingTopBarSampleGroups.kt @@ -18,6 +18,7 @@ package com.flaringapp.compose.topbar.sample.shared.ui.samples import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.AppBarScrimSample import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.AppBarShadowSample +import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.BodyResizeSample import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.FloatingElementSample import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.ManualCollapsingControlsSample import com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced.ParallaxCollapsingSample @@ -67,6 +68,7 @@ object CollapsingTopBarSampleGroups { AppBarShadowSample, AppBarScrimSample, ManualCollapsingControlsSample, + BodyResizeSample, FloatingElementSample, ) diff --git a/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt new file mode 100644 index 0000000..a5665c8 --- /dev/null +++ b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt @@ -0,0 +1,122 @@ +/* + * Copyright 2026 Flaringapp + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import com.flaringapp.compose.topbar.sample.shared.ui.samples.CollapsingTopBarSample +import com.flaringapp.compose.topbar.sample.shared.ui.samples.CollapsingTopBarSampleDogDefaults +import com.flaringapp.compose.topbar.sample.shared.ui.samples.common.SampleTopAppBar +import com.flaringapp.compose.topbar.sample.shared.ui.samples.common.SampleTopBarImage +import com.flaringapp.compose.topbar.sample.shared.ui.theme.ComposeCollapsingTopBarTheme +import com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffold +import com.flaringapp.compose.topbar.scaffold.CollapsingTopBarScaffoldScrollMode + +object BodyResizeSample : CollapsingTopBarSample { + + override val name: String = "Body Resize" + + @Composable + override fun Content(onBack: () -> Unit) { + BodyResizeSampleContent(onBack = onBack) + } +} + +@Composable +fun BodyResizeSampleContent( + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + Surface( + modifier = modifier.fillMaxSize(), + ) { + CollapsingContent( + onBack = onBack, + ) + } +} + +@Composable +private fun CollapsingContent( + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + CollapsingTopBarScaffold( + modifier = modifier, + scrollMode = CollapsingTopBarScaffoldScrollMode.collapse(expandAlways = false), + topBar = { + SampleTopBarImage( + dog = CollapsingTopBarSampleDogDefaults.Advanced, + ) + + SampleTopAppBar( + title = "Body Resize", + onBack = onBack, + containerColor = Color.Transparent, + ) + }, + body = { + GradientContent( + modifier = Modifier.resizeWithCollapse(), + ) + }, + ) +} + +@Composable +private fun GradientContent( + modifier: Modifier = Modifier, +) { + val colorScheme = MaterialTheme.colorScheme + val gradient = remember(colorScheme) { + Brush.verticalGradient( + colors = listOf( + colorScheme.primary, + colorScheme.surface, + colorScheme.tertiaryContainer, + ), + ) + } + + Spacer( + modifier = modifier + .fillMaxSize() + .background(gradient) + .verticalScroll(rememberScrollState()), + ) +} + +@Preview +@Composable +private fun Preview() { + ComposeCollapsingTopBarTheme { + BodyResizeSampleContent( + onBack = {}, + ) + } +} From dd58a2f7516bf6dc2d78bb236fc011ac5fef11e8 Mon Sep 17 00:00:00 2001 From: Flaringapp Date: Sat, 4 Apr 2026 22:48:40 +0300 Subject: [PATCH 5/5] Add centered text to sample gradient body --- .../shared/ui/samples/advanced/BodyResizeSample.kt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt index a5665c8..fe68380 100644 --- a/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt +++ b/sample/shared/src/commonMain/kotlin/com/flaringapp/compose/topbar/sample/shared/ui/samples/advanced/BodyResizeSample.kt @@ -17,14 +17,16 @@ package com.flaringapp.compose.topbar.sample.shared.ui.samples.advanced import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color @@ -103,12 +105,15 @@ private fun GradientContent( ) } - Spacer( + Box( modifier = modifier .fillMaxSize() .background(gradient) .verticalScroll(rememberScrollState()), - ) + contentAlignment = Alignment.Center, + ) { + Text("Center") + } } @Preview