Replace Cloudy with Coil BlurTransformation for unblurred album art issue. Made-with: Cursor
2.1 KiB
2.1 KiB
Design: Heavy Blur Background via Coil BlurTransformation
Date: 2026-03-18
Status: Approved
Problem
The player screen's blurred album art background uses the Cloudy library at its maximum radius of 25. This is insufficient — album art with text remains legible and fine details are still visible, breaking the intended "washed out background" aesthetic.
Solution
Replace Cloudy with a self-contained Stackblur BlurTransformation applied via Coil's image loading pipeline. Blur is baked into the decoded bitmap on a background thread, producing a heavily smeared result with no legible text or sharp edges.
Changes
1. Add BlurTransformation.kt
Create app/src/main/java/xyz/cottongin/radio247/ui/util/BlurTransformation.kt.
A ~130-line pure Kotlin + Android bitmap Stackblur implementation (no new library dependency). Accepts:
radius: Int— blur radius (25 is already very aggressive at low scale)scale: Float— downsample factor applied before blurring (0.1f = 10% of original size)
2. Update BlurredBackground in NowPlayingScreen.kt
- Remove
.cloudy(radius = 25)modifier - Remove
size(10, 10)from theImageRequest(scale parameter in the transformation handles downsampling) - Add
transformations(BlurTransformation(radius = 25, scale = 0.1f))to theImageRequest - Remove Cloudy import
3. Remove Cloudy dependency
- Remove
implementation(libs.cloudy)fromapp/build.gradle.kts - Remove
cloudyversion and library entries fromgradle/libs.versions.toml
Parameters
| Parameter | Value | Rationale |
|---|---|---|
radius |
25 | Maximum effective Stackblur radius before diminishing returns |
scale |
0.1f | Downsamples to 10% before blurring, destroying fine detail and text |
Trade-offs
- No new dependency — implementation is inlined as a project file
- All API levels — pure bitmap manipulation, no RenderEffect/RenderScript
- Background thread — blur computed by Coil pipeline, zero per-frame GPU cost
- Not animatable — blur is baked at load time; cannot be animated at runtime (acceptable for this use case)