Skip to content

feat: stack-blur backdrop for navbar/menu below API 31 - #1486

Closed
sang765 wants to merge 1 commit into
rukamori:devfrom
sang765:feat/api30-backdrop-blur-stackblur
Closed

sang765 wants to merge 1 commit into
rukamori:devfrom
sang765:feat/api30-backdrop-blur-stackblur

Conversation

@sang765

@sang765 sang765 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Summary

RenderEffect/Haze cannot blur live content below Android 12 (API 31), so on those devices the new floating navigation bar and the top-app-bar overflow menu degraded to a flat tint.

This makes them show a real backdrop blur there by capturing the hazeSource content into a GraphicsLayer, reading it back, downscaling it and blurring it with the existing pure-Kotlin ImageBlurUtils stack blur, then rendering it behind the bar/menu.

The capture modifier is a no-op on API >= 31, so the modern Haze/RenderEffect path is untouched and pays zero cost.

Changes

  • ui/component/BackdropSnapshot.kt (new) — BackdropSnapshot holder + Modifier.backdropSnapshotSource(), which records the node, reads it back on a throttled loop (periodic for the navbar, gated on expanded for the menu), downscales to <= 480px and stack-blurs into the holder.
  • ui/component/FloatingBarBlurBackground.kt — API < 31 branch renders the blurred snapshot (ContentScale.Crop, BottomCenter) + tint. Adds optional backdrop param (default null, so the MiniPlayer path is unchanged).
  • ui/component/FloatingNavigationToolbar.kt — passes backdrop through to FloatingBarBlurBackground.
  • ui/component/TopAppBarOverflowMenu.kt — API < 31 branch renders the blurred snapshot (ContentScale.Crop, TopEnd) + tint; extracts the shared menu items into OverflowMenuItems.
  • MainActivity.kt — creates the two holders, attaches the capture to the two hazeSource nodes, gates the menu holder on expanded, and passes backdrop to the two consumers.

Notes / limitations

  • The backdrop is a snapshot approximation (bottom-center strip behind the navbar, top-right region behind the menu), not pixel-perfect live blur like Haze — acceptable once blurred, but worth eyeballing on a real API 30/31 device.
  • Blur radii (navbar 10px, menu 18px on the <= 480px snapshot) and tint alphas mirror the current Haze style values; easy to tune.
  • Not build-verified on an API < 31 device in this environment.

@sang765
sang765 force-pushed the feat/api30-backdrop-blur-stackblur branch 4 times, most recently from 34df937 to 893fc23 Compare October 20, 2026 16:05
RenderEffect/Haze cannot blur live content below Android 12 (API 31), so
the floating navigation bar and top-app-bar overflow menu degraded to a
flat tint there.

On API < 31, record the hazeSource content into a GraphicsLayer, read it
back, downscale it and blur it with the existing pure-Kotlin
ImageBlurUtils stack blur, then render it behind the bar/menu. The
capture modifier is a no-op on API >= 31, keeping the modern
Haze/RenderEffect path untouched at zero cost.
@sang765
sang765 force-pushed the feat/api30-backdrop-blur-stackblur branch from 893fc23 to 727a951 Compare October 21, 2026 02:11
@sang765

sang765 commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Drop

@sang765 sang765 closed this Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant