liquid_glass_easy 3.5.0
liquid_glass_easy: ^3.5.0 copied to clipboard
A Flutter package that provides real-time liquid glass lens effects with distortion, magnification, refraction, and blur for stunning UI visuals.
3.5.0 #
- New —
LiquidGlassTouch/LiquidGlassFlex: a surface that deforms under a finger. Glass could move and it could re-tint, but it could not answer a press with its own geometry. The newtouch:parameter — onLiquidGlassLens,LiquidGlassButton,LiquidGlassAppBarandLiquidGlassTabBarAction— takes aLiquidGlassTouchcarrying aLiquidGlassFlex, and the surface becomes a soft body: press and it swells under the finger, drag and it elongates along the pull, pinches in the cross axis, leans after the finger, then springs back with a wobble on release. The lens itself never moves — its footprint in layout is unchanged, so neighbouring widgets never shift as it wobbles. Unlike a scale transform, which can only grow symmetrically around one anchor, the left/right/top/bottom edges spring independently toward their own targets, so the half nearest your finger deforms more than the far half.nullis the default and adds nothing to the tree: no gesture listener, no ticker, no cost on an untouched lens. The bars (LiquidGlassTabBar,LiquidGlassBottomNavBar) deliberately do not take it — a navigation bar that deforms under a stray drag reads as broken rather than as soft — and neither doLiquidGlassSlider/LiquidGlassToggle, whose touch response is already the jelly. - Nine direct knobs, five behind
LiquidGlassFlexAdvanced:stretch(peak elongation in logical px),squeeze(the along-axis gain is taken back out of the cross axis — elongate horizontally and the lens genuinely gets thinner),lean(how far the body slides after the finger),grip(0= every edge shares the deformation wherever you touched,1= the edges nearest your finger take all of it),compressInward(driving the grabbed edge into the body squashes it instead of inflating it whichever way it is shoved),holdScale(signed swell for as long as the finger is down),tapScale(a one-shot pop fired when a tap completes, so a fast click still reads as a click),maxPull(thetanhsaturation point) andlockAxis(pins the cross axis for shapes whose proportions carry meaning — a nav capsule, a slider track). Content follow, the optical boosts and the three spring constants live inadvanced..subtle(),.uniform()and.pronounced()are tuned presets. - The content rides the glass.
childFollowblends the child's transform toward the lens's own map, and at1the two are literally the same expression — so the content cannot drift off the surface however hard the lens is pulled. The child is laid out at rest size and then transformed, so text never re-wraps and rows never re-space mid-gesture. - A press deepens the optics rather than zooming the backdrop.
refractionBoostscales the refraction itself (through a configuredLiquidGlassRefractionType's own strength when one is set, so a type is not bypassed). The backdrop zoom is a separate knob,magnificationBoost, off by default — magnification is not a refraction depth, and raising it reads as the picture behind the glass sliding rather than the glass bending. - Correct outlines under deformation. The shader evaluates the shape at rest size in a domain divided by the deformation scale, and the clips are stretched to match — so a stretched circle becomes an ellipse instead of a stadium with flat runs, and the clip never crosses the glass and shaves the rim at a cap apex.
- Works inside
LiquidGlassBlender. A deformed member resizes its own box, the blender derives every member rect from the render tree, and the merged metaball silhouette picks the deformation up on its own. The one thing that does not survive the merge isrefractionBoost: the blender refracts the whole surface through a single shared style, so a press on one blob cannot deepen its own optics without deepening every other blob's. All geometry —stretch,squeeze,lean,grip,holdScale,tapScale— pluschildFollowbehave normally. - One finger owns a lens. The driver holds a single grab point and a single accumulated pull, and gestures arrive through a translucent
Listener(never aGestureDetector, so a press can never join the gesture arena and steal taps from the content inside the lens or fight a scrollable beneath it). Pointer events are therefore filtered by identity: the first finger down claims the lens and keeps it until it lifts, a second touch cannot reset the grab point mid-gesture, and a non-owner lifting does not end the press. - Fix —
flutter build webfails withUndefined name 'internal'(reported on Flutter 3.29 / Dart 3.7.2, dart2js):liquid_glass_view.dartandliquid_glass_blender.dartannotate members with@internalbut did not importpackage:meta/meta.dart.package:flutter/foundation.dartonly re-exportsinternalon newer SDKs, so on 3.29 the name resolved to nothing and the compile aborted — for every consumer of the package, whether or not they used the annotated APIs, since the whole library is compiled either way. Both files now import meta directly, carrying an// ignore: unnecessary_importbecause newer SDKs correctly flag the import as redundant.metawas already a declared dependency; nothing else changes. - Example: new glass list page (a single lens holding a four-row list, with every flex value on sliders) and a standalone flex tuner that emits the tuned spec as copy-pasteable Dart.
3.4.0 #
- New — SVG / PNG / any-widget icons in the nav and tab bars (
LiquidGlassTabBarItem.iconBuilder): tab glyphs were locked toIconData, so an SVG or a bitmap could not be used at all. An item can now draw itself:iconBuilderis handed aLiquidGlassGlyphcarrying the already resolved color for the layer being drawn, the glyph box size, and whether that layer renders the selected state — so tinting withglyph.colorand switching artwork onglyph.selectedreproduces exactly whaticon+selectedIcondo. This matters on the glass-pill bar, which draws every tab twice per frame (one copy clipped inside the moving pill, one outside it): the builder runs once per layer with that layer's color, so custom artwork gets the same iOS-26 reveal as a built-in icon instead of sitting frozen while the pill sweeps past. Honored by every tier — the plain bar, the sliding bar, the glass-pill bar andLiquidGlassTabBar. UseLiquidGlassTabBarItem.custom(...)for asset-only tabs (noIconDataneeded), and mix builder items andIconDataitems freely in one bar. Custom content is boxed to the item style'siconSizeand scaled down if larger, so a glyph can never grow its cell and desync the pill geometry from the icon it reveals. No new package dependency — bring your own SVG/image library. - New —
LiquidGlassButton.childandLiquidGlassTabBarAction.child: both components hardcoded their content (an icon + label row; a single glyph), so anything else — an SVG, an image, a badge, two lines of text — was impossible.childreplaces that content entirely, withLiquidGlassButton.custom(...)/LiquidGlassTabBarAction.custom(...)for the content-only form. The widget is centered and clipped to the glass shape and never sizes its host: the button stays on itswidth/heightand the action stays asize-diameter circle, so the lens geometry holds. A bareIcon/Textinside inherits the host'sforegroundColor(and the button'sfontSize/fontWeight/iconSize), so it matches the built-in look by default; give the widget its own color to paint it yourself. - Additive release: no field types changed and no new required parameters, so existing code compiles and renders identically.
3.3.1 #
- Fix —
flutter build webfails on Flutter 3.44+ (impellerc failure: Compilation failed for target: SkSL): Flutter 3.44 started validating every shader in the package manifest against SkSL at build time, and the Impeller-only entries use the hardware-derivative gradient (dFdx(float)) — invalid SkSL — so the web build died even though those entries are never loaded on web. The derivative path is now guarded behind impellerc'sSKIA_GRAPHICS_BACKENDdefine: when a shader is compiled for the SkSL target it falls back to the analytic (derivative-free) gradient, so all entries compile clean. Native Impeller output is byte-identical — real devices keep the cheap 1-tap derivative path — and the runtime per-backend shader selection is unchanged.
3.3.0 #
- New —
OpticalBorder.lightSpread: controls how far the optical rim's directional highlight wraps around the perimeter, independent of the always-on ambient ring.0.0= tight, concentrated glint hugging the light axis,0.5= default (identical to the previous fixed falloff, so existing code renders unchanged),1.0= highlight wraps almost all the way around. Below0.5the angular window of each light lobe narrows — the bright core itself tightens, not just the dim tail. Applies toLiquidGlassLens, the border-only painter, and theLiquidGlassBlendermetaball rim.
3.2.2 #
- Fix — vertically mirrored refraction on OpenGL ES (emulators): Flutter's OpenGLES coordinate-system unification (engine after 3.44.0) removed the framebuffer Y-flip, which turned the shaders' manual sampler/derivative Y-flips into a double flip — a symmetrical Y-axis refraction artifact visible on Android emulators that fall back to OpenGL ES (real Vulkan/Metal devices were never affected). All four
IMPELLER_TARGET_OPENGLESflips are now guarded by#ifndef IMPELLER_OPENGLES_UNFLIPPED_DEPRECATED, so they apply only on older engines and are skipped once the engine sets the macro. Skia/web and Vulkan/Metal are unchanged.
3.2.1 #
- Fix — bottom nav bar tab selection on web: clicking a tab on web could select the wrong tab (the neighbour), walk toward the target one click at a time, or not change selection at all — most noticeable with a trackpad. A quick click was being routed through the hold-to-drag path and committing to the glide's lagging position instead of the cell that was pressed. A click now commits to the pressed tab. The tap-and-hold drag gesture is unchanged.
3.2.0 #
- Per-backend single-lens shaders: the shape-gradient method now differs by engine. Impeller keeps the hardware-derivative (
dFdx) gradient, while Skia/web loads a separateliquid_glass_skia.frag/liquid_glass_border_skia.fragthat selects an analytic gradient instead —dFdxis invalid SkSL, so the previous shared program was only correct on Impeller. Programs are cached per backend and resolved automatically; the frosted fallback now also covers the brief async load when a lens mounts on a backend that wasn't preloaded. LiquidGlassShadersAPI (backward-compatible):ensureLoaded,isLoaded/isLoadedFor,createMainShader, andcreateBorderShadernow accept an optionalimpellerflag, defaulting to the engine's native backend (ui.ImageFilter.isShaderFilterSupported). Existing no-argument calls keep working.- Metaball blend on Skia — quality + blur: the merged smooth-union field now propagates an analytic gradient (the h-weighted blend of the per-lens gradients) on Skia instead of the heavier 5-tap, and in-shader blur is re-enabled on the Skia blend path. Chromatic aberration is applied per blur tap, so CA lands before the blur (matching Impeller's order).
- Blender Impeller perf — tight engine-blur clip: on the Impeller engine-blur path the costly backdrop + blur pass is now clipped to the tight glass region (the blob union plus rim/blur/refraction/bridge margin) instead of the whole surface. The shader is packed in that clip-local frame — lens centres, resolution, and the sampling window all share one coordinate space — so the blob stays locked to the lenses while the expensive pass only covers the glass.
- New —
LiquidGlassBlender.debugClipBounds(off by default): draws a magenta outline around the backdrop clip region on both backends, to verify the costly pass hugs the merged glass. Diagnostic only — it costs a stroked draw every frame; keep itfalsein production. - Example: added a liquid-glass showcase/menu page and an image-backed lens demo to the gallery.
3.1.0 #
- New —
LiquidGlassBlender: blend two to sixLiquidGlassLensdescendants into one liquid surface. Neighbouring lenses fuse with a smooth metaball bridge as they meet and pull apart as they separate, while each member keeps its own corner style. Place it inside aLiquidGlassViewand it works on both backends — Impeller samples the live backdrop, Skia refracts the captured background. - Metaball gradient split: the merged-field normal uses the hardware-derivative 1-tap on Impeller and a 5-tap central difference on Skia (whose SkSL has no
dFdx), selected per backend so the blend loads and renders on both. - Single-lens shaders now use the exact 5-tap gradient for every corner style.
- Chromatic aberration on the Skia blend path is now applied after the blur (matching Impeller's order); in-shader blur is disabled on the Skia blend path for now.
- Note: the blend is not optimized for Skia yet — it works on the Skia capture path but can be heavy there; best performance is on Impeller for now.
3.0.0 #
- New — lens anywhere:
LiquidGlassLensis a layout-driven lens you can drop anywhere in the widget tree (no position/size params; size comes from layout). It supports both Impeller and Skia automatically, resolving the best render path for the running engine: on Impeller it refracts the live backdrop with noLiquidGlassViewand no background widget at all; on Skia it refracts an ancestorLiquidGlassView's captured background, and gracefully degrades to a frosted look when neither is available. - New:
LiquidGlassStyle— one shared descriptor (shape + appearance + refraction) for every glass surface (lens, components, nav pill), withcopyWith(...)andmerge(...). - New — jelly motion: the
LiquidGlassSlider,LiquidGlassToggle, andLiquidGlassBottomNavBarnow share an iOS-style jelly spring — squash/stretch with a direction-memory spring and momentum-sided squash. The slider/toggle thumb stretches toward its travel and snaps back, and the nav bar's selection pill springs between items. Exposed standalone as the reusableLiquidGlassJellywidget. - New components:
LiquidGlassSlider,LiquidGlassToggle,LiquidGlassAppBar,LiquidGlassScaffold(owns the glass pipeline),LiquidGlassDraggable, andLiquidGlassJellyjoin the existingLiquidGlassButton,LiquidGlassBottomNavBar, andLiquidGlassTabBar. - Migration: the old position-driven lens API (
LiquidGlass) is superseded byLiquidGlassLensand the drop-in components; write new code againstLiquidGlassLens. - Breaking: removed the
LiquidGlassSearchBarcomponent. - Breaking:
LiquidGlassAppIconandLiquidGlassDockare no longer part of the public API (kept internally for maintenance). - Rewrote the README around the lens-anywhere API and consolidated the example into a single
main.dartgallery whose home menu opens each demo as its own route. - New shape:
LiquidGlassShape.continuousRoundedRectangle(...)— an Apple capsule-style continuous rounded rectangle, now the default shape; it collapses to a clean capsule at full corner radius. - Breaking: removed
SuperellipseShape; its L^n squircle now lives onLiquidGlassShape.squircle(...)(same iOS-style continuous-curvature look) and ships with its own exact, shader-matchedClipPathclipper (viaclipQuality: LiquidGlassClipQuality.exact). The old superellipse had no exact Flutter clip path, which forced a rectangle clip and capped its blur; the squircle's dedicated clipper now matches the SDF the shader draws and blurs correctly at any sigma. - Shapes are now selected via the
LiquidGlassShape.roundedRectangle(...)/.squircle(...)/.continuousRoundedRectangle(...)convenience constructors (a singlecornerStylevocabulary) instead of separateRoundedRectangleShape/SuperellipseShapeclasses. - Simplified the shaders: removed the superellipse SDF branch and the
u_shapeTypeuniform, so every lens now uses the analytic rounded-rect path. - Added
LiquidGlassView.regionCapture(off by default): per-lens region capture on the Skia sync path — each capture grabs only every lens's own rect (+ margin) instead of the whole background. A performance win when lenses cover a small part of a large background; no effect on Impeller.
2.0.1 #
- Fixed lens position being clamped to the parent bounds even when
outOfBoundaries: true. A lens moved past the parent's edge (in any direction) now keeps its true position instead of being pinned, so spacing between lenses stays correct.
2.0.0 #
- Added optical border mode (
OpticalBorder) — Apple-style, SDF-based rim lighting with background-tinted highlights, dual-sided specular reflections, and a lens height profile — alongside the existingClassicBorder. - Added new ready-made components:
LiquidGlassButton,LiquidGlassSearchBar,LiquidGlassAppIcon,LiquidGlassDock,LiquidGlassTabBar, andLiquidGlassBottomNavBar. - Improved rendering stability on release/profile builds with Impeller.
- Fixed lens and border content rendering upside down on Impeller's OpenGL ES backend (older Android devices) by inverting the texture sample Y-axis under
IMPELLER_TARGET_OPENGLES. - Breaking:
oneSideLightIntensityanddoubleSideLightIntensitymoved from the shape toClassicBorder. Pass them viaborderType: ClassicBorder(...)instead of directly on the shape.
1.1.1 #
- Formatted the dart files and changed the size of the thumbnail of screenshot.
1.1.0 #
- Added new refraction modes: shape refraction and radial refraction.
- Added new light modes: edge and radial.
- Added chromatic aberration support.
- Added one side light intensity support.
- Added saturation control.
- Updated magnification behavior to apply to the entire lens area rather than only the distortion region.
- Improved and optimized shader code.
- Removed
highDistortionOnCurves; the same effect can now be achieved by increasingdistortionand settingdistortionWidthto half of the smallest lens dimension.
1.0.0 #
Initial Stable Release – Liquid Glass Easy
- First official release of the
liquid_glass_easyFlutter package. - Provides real-time liquid glass lens effects with smooth distortion, magnification, and refraction.
- Built with shader-based rendering for high performance and flexibility.
- Includes
LiquidGlassViewandLiquidGlasswidgets for quick and easy integration into any UI. - Example app included to demonstrate usage, configuration, and visual styles.
- Ready for production and pub.dev distribution.