Blur usageΒΆ
Blur works with either source-backed content or the modifier's own content. Both modes use the
typed hazeBlur modifier and the same replayable Style.
Source-backed BlurΒΆ
val hazeState = rememberHazeState()
val style = HazeMaterials.thin()
Box {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.hazeSource(hazeState),
) {
// Content
}
TopAppBar(
modifier = Modifier.hazeBlur(
input = HazeInput.Sources(hazeState),
style = style,
),
)
}
HazeInput.Sources also owns source selection and retained-output behavior. The default
KeepLastFrame policy avoids an empty flash during source transitions. Use
ClearWhenUnavailable for privacy-sensitive content:
Modifier.hazeBlur(
input = HazeInput.Sources(
state = hazeState,
retention = HazeSourceRetention.ClearWhenUnavailable,
),
)
Own-content BlurΒΆ
Use HazeInput.Content when the modifier's own content is the input:
Image(
modifier = Modifier.hazeBlur(
input = HazeInput.Content,
style = HazeMaterials.thin(),
),
)
Enabling BlurΒΆ
Blur is enabled by default only where Haze considers the platform implementation reliable. To
override that decision, write blurEnabled in a Style:
Modifier.hazeBlur(
input = HazeInput.Sources(hazeState),
style = HazeBlurStyle {
blurEnabled(true)
},
)
When Blur is disabled, Haze draws the configured fallback scrim instead.
Replayable StylesΒΆ
HazeBlurStyle is an opaque program of Blur-specific writes:
val style = HazeBlurStyle {
blurEnabled(true)
blurRadius(20.dp)
noiseFactor(0.15f)
backgroundColor(Color.Black)
colorEffects(
listOf(
HazeColorEffect.tint(Color.White.copy(alpha = 0.12f)),
),
)
fallbackColorEffect(HazeColorEffect.tint(Color.Black.copy(alpha = 0.7f)))
alpha(1f)
mask(null)
progressive(null)
blurredEdgeTreatment(BlurredEdgeTreatment.Rectangle)
}
Style resolution always replays these tiers in order:
HazeBlurDefaults.styleLocalHazeBlurStyle- The explicit
hazeBlurStyle
The last write to a property wins, both across tiers and within a Style chain:
val compact = HazeMaterials.thin().then {
blurRadius(12.dp)
noiseFactor(0f)
}
If a replacement Style omits blurRadius, the local or default value becomes visible again. Styles
are immutable and safe to share; create a replacement Style when the appearance needs to change.
Caller-owned color-effect lists are snapshotted when the Style is created. An explicit empty list clears inherited color effects:
val noColorEffects = HazeBlurStyle {
colorEffects(emptyList())
}
Progressive Blur and masksΒΆ
Progressive Blur varies intensity across the surface:
val progressiveStyle = HazeBlurStyle {
progressive(
HazeProgressive.verticalGradient(
startIntensity = 1f,
endIntensity = 0f,
),
)
}
A mask fades the effect's opacity and is usually cheaper:
val maskedStyle = HazeBlurStyle {
mask(
Brush.verticalGradient(
colors = listOf(Color.Black, Color.Transparent),
),
)
}
Input scaleΒΆ
Sampling and layer expansionΒΆ
Sampling and layer expansion are structural modifier policies, not Style properties:
Modifier.hazeBlur(
input = HazeInput.Sources(hazeState),
style = style,
sampling = HazeSampling.Adaptive,
expandLayerBounds = true,
)
HazeSampling.DefaultandAdaptivelet Blur balance quality and cost automatically.HazeSampling.FullResolutiondisables input downscaling.HazeSampling.Fixed(pixelFraction)retains a fixed fraction of the full-resolution input pixels when you need a predictable trade-off.
Start with the default. Override it only after comparing visual quality and performance on the devices you support.