fresnel_android
Android implementation of fresnel.
Apps depend on fresnel, which selects this package automatically on Android.
What it does
Android has no Liquid Glass, and this package does not pretend otherwise. It has two jobs.
Report capabilities honestly. Without it the façade falls back to
GlassCapabilities.unsupported(), which claims reduce-motion and
increase-contrast are off rather than asking. Those flags are exactly the ones
the shader path has to honour itself — on the native path the OS does it for
us — so guessing them wrong is an accessibility failure, not a cosmetic one.
| Contract member | Android |
|---|---|
capabilities() |
native, via a Kotlin method channel |
buildNativeGlass() |
null — façade uses the shader |
buildNativeContainer() |
null — façade uses the shader |
renderSymbol() |
null — no SF Symbols |
Hand widgets the right tokens. AndroidGlassTokens carries the Material 3
Expressive corner scale and motion scheme, so a surface that cannot be glass
degrades to something that looks like Android instead of a flattened iOS
control.
import 'package:fresnel_android/fresnel_android.dart';
GlassSurface(
shape: AndroidGlassTokens.shapeExtraLarge,
child: const Text('Hello'),
)
How the accessibility flags are read
- reduceMotion —
Settings.Global.TRANSITION_ANIMATION_SCALE == 0, withANIMATOR_DURATION_SCALEas a second probe because some OEM skins zero only one of the two. Android has noisReduceMotionEnabled, andAccessibilityManager.isEnabledis not a stand-in: it is true whenever any accessibility service runs, TalkBack included, and TalkBack users have not asked for animations to stop. - increaseContrast —
UiModeManager.getContrast() > 0on API 34+, the only public API for it. Below that, the securehigh_text_contrast_enabledkey (stable since API 21 but@hide) and colour inversion. - reduceTransparency — always false. Android has no such preference, and deriving one from "Remove animations" would make every surface opaque for users who only asked for stillness.
- osMajorVersion — deliberately not sent. The contract documents it as null off Apple platforms, and an API level in a field callers read as an Apple major version is worse than no value.
No permissions are declared; every setting read here is world-readable.
Why the tokens are what they are
Material 3 Expressive replaced the duration/easing motion tokens with a
spring-based scheme in two families. Spatial springs move things and are
underdamped on purpose, so they overshoot — that overshoot is the
expressiveness. Effects springs change colour, opacity and elevation and are
critically damped, because an overshooting colour reads as a flicker.
AndroidGlassTokens exposes both, plus the emphasized duration/curve set for
the parts of Flutter's animation API that still want a fixed time.
The shape defaults follow suit: defaultShape is the 16dp large corner, and
shapeFull is a capsule with true circular arcs rather than a superellipse.
The squircle is Apple's corner; using it here would be the exact mistake this
package exists to avoid.
Layout
lib/fresnel_android.dart FresnelAndroid, the platform impl
lib/src/android_glass_tokens.dart the M3 Expressive shape + motion tokens
android/build.gradle.kts
android/src/main/AndroidManifest.xml
android/src/main/kotlin/com/waqaralisiyal/fresnel_android/
FresnelAndroidPlugin.kt getCapabilities, and nothing else
License
MIT. See LICENSE.
Libraries
- fresnel_android
- Android implementation of
fresnel.