NutrientDocumentStatusBarScrim

fun NutrientDocumentStatusBarScrim(documentState: DocumentState, state: NutrientBackdropState, modifier: Modifier = Modifier, color: Color = NutrientStatusBarScrimDefaults.tint(), blurRadius: Dp = NutrientStatusBarScrimDefaults.BlurRadius, windowInsets: WindowInsets = WindowInsets.statusBars)

NutrientStatusBarScrim that decides for itself how much to show, from the document's own state.

The plain NutrientStatusBarScrim takes visible from the caller, which suits a host that already knows when its chrome is up. This variant is for the common case: it shows the scrim only while the SDK main toolbar is disabled (so nothing else is painting the strip) and the UI is not in immersive mode, and it brings the scrim up as the page scrolls or zooms into the strip. See statusBarScrimIntensity for what each condition rules out and how the strength is derived.

Because the page's position is one of the inputs, the scrim comes and goes with the document — zooming out to fit the page drops the page below the strip and the scrim leaves with it. Both the position-tracking here and the spring it is smoothed with (NutrientStatusBarScrimDefaults.fadeSpec) are there so that this is never seen as a switch: a slow scroll grows the scrim with the page, and a fling that crosses the strip in a frame is carried the rest of the way by the fade. A host that wants the strip covered unconditionally should use NutrientStatusBarScrim directly with its own visible.

Setting up

Three pieces, all in one composition:

  1. Create the shared backdrop once, in the composable that owns both the document and the chrome: val backdrop = rememberNutrientBackdropState(). It is the handle the document records into and the scrim reads from, so both must receive the same instance — remembering it one level above them is what guarantees that. Do not create one per child.

  2. Put nutrientBackdropSource on the DocumentView, last in its modifier chain. The view then records its rendered pages into the backdrop on every frame it draws. It goes on the document and nowhere else: the scrim blurs whatever was recorded, so on any other composable it would blur that composable instead. See nutrientBackdropSource for the full contract.

  3. Declare this scrim after the DocumentView, in the same Box, aligned to the top. The order matters twice over: the scrim samples what has already drawn this frame, and later children paint over earlier ones, which is the stacking you want. Any custom toolbar goes after the scrim, offset below the status bar with statusBarsPadding().

@Composable
fun FloatingToolbarDocument(documentState: DocumentState) {
val backdrop = rememberNutrientBackdropState()

Box(Modifier.fillMaxSize()) {
DocumentView(
documentState = documentState,
modifier = Modifier
.fillMaxSize()
.nutrientBackdropSource(backdrop),
)
NutrientDocumentStatusBarScrim(
documentState = documentState,
state = backdrop,
modifier = Modifier.align(Alignment.TopCenter),
)
// … the floating toolbar …
}
}

Two things to avoid. The document's configuration must have defaultToolbarEnabled(false); with the SDK's own toolbar mounted the strip is already covered and this scrim stays off. And do not put a Modifier.graphicsLayer, alpha or shadow on an ancestor between the document and the scrim — NutrientBackdropState explains how that can leave the blur holding a stale frame.

Parameters

documentState

The state driving the com.pspdfkit.jetpack.compose.views.DocumentView this scrim sits over.

state

The backdrop the DocumentView records into through nutrientBackdropSource. Pass the same instance; see Setting up above.

modifier

Applied to the strip. Align it to the top of the parent.

color

Tint painted over the blur. Also the entire effect below API 31. Defaults to NutrientStatusBarScrimDefaults.tint.

blurRadius

Blur applied to the content behind the strip; 0.dp paints color only.

windowInsets

The strip's height; defaults to WindowInsets.Companion.statusBars.