Beautiful gradient wallpapers for Android — generated, previewed, and applied in seconds.
- Highlights
- Features
- Download
- Getting Started
- Permissions
- How It Works
- Key Files / Structure
- Adding a New Effect
- Troubleshooting
- Contributing
- Community
- License
| 🎨 4 Gradient Styles | Linear, Radial, Angular (sweep), Diamond — each with a 0°–360° rotation slider |
| ✨ 5 Visual Effects | Snow, Stripes, Glass overlay, Geometric grid, Blur — each with individual opacity |
| 👁 Live Preview Mode | Fullscreen overlay to tweak style, angle & effects before applying |
| ❤️ Favourites | Snapshot any wallpaper including exact effects & alphas; import/export as .wall |
| 📤 Share Anywhere | Export as PNG, .wall, SVG, or production-ready CSS |
| 🎛 Two Interaction Modes | Simple (tap → apply) or Advanced (tap → live preview) |
| 🎵 Haptic Feedback | Toggleable, context-sensitive — snaps at 90° angle checkpoints |
| 🔔 Auto Update Check | Silent GitHub releases check on launch |
| 💎 Material You | Dynamic color, floating nav bar, animated chips, spring physics |
- Generate grids of 12, 16, or 20 wallpapers per refresh.
- Portrait (9:16) and Landscape (16:9) preview and bitmap output.
- Select up to 5 custom colors via HSV picker, or let the app generate random palettes.
- Three tone modes: Dark, Neutral, Light — applied during color generation and shading.
- Multi-color mode produces 3–5 stop gradients.
- Toggle any combination of gradient types per session.
| Effect | Description |
|---|---|
| ❄️ Snow | Film-grain-style random white specks |
| 〰️ Stripes | Diagonal translucent stripe pattern |
| 🪟 Glass | Nothing-style subtle glass overlay |
| 🔲 Geometric | Grid and circle line overlay |
| 💧 Blur | Full-image Stack Blur — pure Kotlin, no RenderScript |
Each effect has a 0–100% opacity slider in Advanced mode. Effects are snapshotted with favourites so the saved look is reproduced exactly on any device.
- Fullscreen wallpaper render in a device-frame style box.
- Switch gradient style and drag the angle slider without leaving the preview.
- Angle slider snaps to 90° increments with haptic feedback.
- Per-effect chips with a fill-progress bar showing current alpha.
- Heart button inside preview to favourite the current configuration.
- Done opens the apply/download dialog directly from the overlay.
- Heart any wallpaper from the grid or inside the preview.
- Favourites store the exact effect flags and opacities at save time.
- Reverse-chronological grid; supports portrait/landscape toggle.
- Import individual
.wallfiles or bulk-import multiple at once. - Export all favourites as a single
.wallfile to share or back up.
- Apply to Home screen, Lock screen, or Both.
- Download as PNG to
Pictures/Wallervia MediaStore. - Share as PNG bitmap,
.wallfile, SVG, or CSS. - SVG export mirrors
BitmapUtilsrendering math exactly (gradient anchoring, stripe pattern, noise filter, base64 overlays). - CSS export produces ready-to-use classes with
linear-gradient/conic-gradient/radial-gradientandfilter: blur()— paste straight into a project.
| Setting | Options |
|---|---|
| App theme | System / Light / Dark |
| Gradient background | On / Off |
| Haptics | On / Off |
| Interaction mode | Simple / Advanced |
| Default orientation | Auto / Portrait / Landscape |
| Default gradient count | 12 / 16 / 20 |
| Default tone mode | Dark / Neutral / Light |
| Default multicolor | On / Off |
| Default effects | Snow / Stripes / Glass pre-enabled |
Grab the latest .apk from the Releases page. Pre-releases are clearly labelled — beta builds often ship new effects or UI experiments ahead of the stable channel.
git clone https://github.com/Pankaj-Meharchandani/Waller.git
cd WallerOpen in Android Studio (Flamingo or newer), let Gradle sync, then run on a device or emulator.
Or from the command line:
./gradlew assembleDebug
./gradlew installDebugTip: To open a
.wallfile from a file manager or another app, just tap it — Waller registers itself as a handler forapplication/octet-streamvia an intent filter in the manifest.
Requirements:
- Android Studio Flamingo or newer
- Kotlin (matching the project Kotlin version)
- Jetpack Compose with Material3
- Min SDK API 26 (Android 8.0) · Tested on Android 11–14
- Blur preview requires API 31+ and degrades gracefully on older devices
| Permission | When required |
|---|---|
WRITE_EXTERNAL_STORAGE |
API ≤ 28 only — saving PNGs to Pictures/Waller |
SET_WALLPAPER |
Normal permission, no runtime prompt needed |
INTERNET |
Update checker — one GitHub API call per launch |
On API 29+ the app uses MediaStore with RELATIVE_PATH and IS_PENDING — no storage permission required. Lock-screen wallpaper (WallpaperManager.FLAG_LOCK) works on API 24+; behavior on some OEM skins (MIUI, One UI) may vary.
ColorUtils.kt works in HSV space to apply tone-biased generation. generateRandomColor(toneMode) clamps the value (brightness) channel to a range matching the selected tone. createShade(color, toneMode, subtle) produces close variations with small hue/saturation/value deltas — making palette pairs feel cohesive rather than arbitrary.
When applying or downloading, createGradientBitmap() draws into an Android Canvas in layer order:
- Gradient —
LinearGradient,RadialGradient, orSweepGradientshader viadrawRect. - Snow — random white circles at ~2% pixel density with randomized alpha.
- Stripes — canvas rotated −45°, soft-fade gradient rects at
width/12spacing. - Glass overlay —
overlay_stripes.pngscaled to canvas with per-alphaPaint. - Geometric overlay —
overlay_geometric.pngscaled to width with per-alphaPaint. - Blur — pure-Kotlin Stack Blur (
stackBlur()), radius 1–25 px scaled byblurAlpha. Applied last so it affects the fully composited image.
WallpaperItemCard and PreviewWallpaperRender mirror the same pipeline using Compose Brush, Canvas drawscope, and Image composables. Angular gradients use a SweepGradient shader drawn via nativeCanvas since Compose's sweep brush doesn't support rotation. Blur uses RenderEffect.createBlurEffect() (API 31+) on a graphicsLayer wrapping only the gradient/effects — keeping the bottom type/color tag sharp outside the blur group.
Favourites are encoded as a delimited string in SharedPreferences. Each entry stores: gradient type, hex color list, 5 effect flags, angle, and 5 alpha floats. The format is backward-compatible — older entries missing alpha fields default to 1f.
A .wall file is JSON produced by kotlinx.serialization:
{
"version": 1,
"walls": [
{
"colors": [-13421773, -6710887],
"gradientType": "Linear",
"angleDeg": 135.0,
"addNoise": false,
"addStripes": true,
"addOverlay": false,
"addGeometric": false,
"addBlur": false,
"noiseAlpha": 1.0,
"stripesAlpha": 0.6,
"overlayAlpha": 1.0,
"geometricAlpha": 1.0,
"blurAlpha": 1.0
}
]
}Colors are ARGB Int values. Multiple wallpapers can be packed into one file for bulk sharing or backup.
ui/
├── WallerApp.kt # Root composable, global state, navigation, persistence
├── wallpaper/
│ ├── WallpaperModels.kt # Wallpaper, GradientType, ToneMode, FavoriteWallpaper
│ ├── WallpaperGeneratorScreen.kt # Home screen — grid, options panel, refresh
│ ├── FavoritesScreen.kt # Favourites grid, import/export, preview
│ ├── ApplyDownloadDialog.kt # Apply / Download / Share dialog
│ ├── BitmapUtils.kt # Bitmap rendering, save, apply, Stack Blur
│ ├── ColorUtils.kt # HSV helpers, random color generation, shading
│ ├── WallpaperSessionState.kt # Per-session state (colors, scroll, gradient types)
│ ├── ShareUtils.kt # PNG / SVG / CSS share helpers
│ ├── Haptics.kt # Global haptic feedback wrapper
│ └── InteractionMode.kt # SIMPLE / ADVANCED enum
│ └── components/
│ ├── WallpaperItemCard.kt # Grid preview card (Compose Canvas rendering)
│ ├── CompactOptionsPanel.kt # Effect/gradient/tone/color chips row
│ ├── Header.kt # App title + orientation chip
│ ├── FloatingNavBar.kt # Animated floating navigation bar
│ ├── EffectsSelector.kt # Switch list (Settings context)
│ └── previewOverlay/
│ ├── WallpaperPreviewOverlay.kt # Fullscreen preview screen
│ ├── PreviewWallpaperRender.kt # Stateless preview renderer
│ ├── PreviewRenderer.kt # Brush/shader factory functions
│ ├── PreviewControlsComponents.kt # Effect chips, sliders, gradient selectors
│ └── PreviewState.kt # Default alpha constants
├── wallfile/
│ ├── WallFile.kt # Serializable data classes for .wall format
│ ├── WallFileManager.kt # Import / export / share .wall files
│ ├── WallConverters.kt # FavoriteWallpaper ↔ WallFavorite converters
│ └── SvgExporter.kt # SVG and CSS file generation
├── settings/
│ ├── SettingsScreen.kt # Settings UI
│ └── AboutScreen.kt # About screen with links
└── onboarding/
├── OnboardingModeDialog.kt # First-launch mode picker
├── UpdateAvailableDialog.kt # Update available dialog
└── UpdateChecker.kt # GitHub releases API check
The architecture is designed so adding a new effect touches two core files plus a handful of wiring files:
Core (rendering logic):
WallpaperModels.kt— add the boolean flag and alphaFloattoFavoriteWallpaper.BitmapUtils.kt— add a drawing block increateGradientBitmap().
Wiring (plumbing the new state through):
WallFile.kt+WallConverters.kt— extend the serializable format and converter.CompactOptionsPanel.kt— add an entry to theeffectslist (icon key + label).WallpaperPreviewOverlay.kt— add anEffectConfigentry and a sliderwhenbranch.WallpaperItemCard.kt+PreviewWallpaperRender.kt— add the Compose Canvas rendering blocks.WallerApp.kt+WallpaperGeneratorScreen.kt+FavoritesScreen.kt— thread state through the call chain.
Architectural note: The dual rendering path (Compose Canvas in
WallpaperItemCardvs. Android Canvas inBitmapUtils) is a known tension. A future refactor toward a sharedEffectRendererinterface would reduce the per-effect file count to 2.
Bitmap looks low resolution on some devices
getScreenSizeForBitmap() uses currentWindowMetrics (API 30+) and subtracts system bar insets. On unusual OEM configurations the returned dimensions can be smaller than expected.
Blur has no visual effect in preview
The Compose RenderEffect blur requires API 31+. On API 30 the blur chip still works but the preview render is a no-op. The bitmap blur (stackBlur) works on all API levels.
Lock screen apply does nothing
Some OEM skins (MIUI, One UI) restrict programmatic lock-screen changes. The app falls back to FLAG_SYSTEM silently — no crash, but the toast will show the failure message.
Save fails on Android 8 or 9
Grant WRITE_EXTERNAL_STORAGE when prompted. The app requests it at the point of saving on API ≤ 28.
Gallery doesn't show the saved image
On API 29+ MediaStore insertion with IS_PENDING = 0 surfaces the file immediately. On older versions a media scanner broadcast is sent. If it still doesn't appear, reboot or navigate to Pictures/Waller in a file manager.
.wall file not recognized by the picker
The picker launches with */* since .wall has no registered MIME type. The app filters to .wall extension after selection, falling back to all selected files if none match.
Contributions are welcome!
- Fork the repo and create a feature branch:
git checkout -b feat/my-feature - Commit with a clear message:
git commit -m "Add my feature" - Push and open a pull request.
Please:
- Keep both rendering paths (Compose + Android Canvas) in sync when touching effect logic.
- Test on both API 30 and API 31+ (blur behavior differs).
- Run through portrait and landscape for any UI change.
- Prefer stdlib/regex over new third-party dependencies for simple tasks.
This project is licensed under the GPL License. See the LICENSE file for details.
Made with ♥ by Pankaj Meharchandani












