Communitygithub.com

roolzksd/droidglass

在任何平台上构建苹果风格的Liquid Glass UI(iOS 26 / macOS 26 外观)。Web、Android WebView、Electron、Capacitor 和 Cordova 获得一款经过测试的引擎,具备真实折射、镜面边缘、融合水滴以及类似 iOS 的弹性按钮、开关、滑块和标签栏。Jetpack Compose 使用 Kyant 的 Backdrop 库;SwiftUI、UIKit 和 AppKit 使用系统 glassEffect。在用户要求液态玻璃、苹果或 iOS 26 玻璃、毛玻璃、磨砂玻璃、玻璃标签栏、玻璃按钮、开关或滑块,或“让它看起来像苹果”时使用,即使没有直接提到“液态玻璃”。

droidglass 是什么?

该技能为开发者提供了一套全面的解决方案,用于在多个平台上实现苹果 iOS 26 / macOS 26 风格的“Liquid Glass”(液态玻璃)UI 效果。其核心不仅包含普通的毛玻璃效果,还模拟了真实的物理折射、镜面高光、边缘彩虹色以及触摸时的弹性形变(如按钮在按下时膨胀并向手指方向拉伸)。技能详细区分了不同平台的原生实现和模拟方案:在 iOS/macOS 上利用系统 API;在 Jetpack Compose 上推荐 Kyant 的 Backdrop 库;在 Web(特别是 Chromium 核心)、Electron、Android WebView 等平台,则提供了一个包含完整效果引擎和 UI 组件的资产包(JavaScript/CSS)。该技能不仅提供了具体的实现步骤和参数配方,还深入阐述了苹果官方的设计规则(如玻璃透明度、仅用于导航控制层、无线性过渡等),并附带了一份详细的发布前检查清单,确保最终效果与原生 Liquid Glass 高度一致,避免出现廉价感。它特别强调了在 Web 上实现时可能遇到的陷阱(如背景根元素、变换动画等)以及无障碍支持。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/roolzksd/DroidGlass/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

DroidGlass: 跨平台的液态玻璃

Liquid Glass 是苹果的一种能折射其下方内容的材料。靠近边缘时,背景会像厚透镜一样被拉向中心,边缘会显示柔和的彩虹色,边缘有一条发丝般的高光线,触摸时玻璃会膨胀、向手指方向拉伸并弹回。普通的毛玻璃效果仅会在白色雾状层下模糊背景,这使得它看起来廉价且有磨砂感。

品味的主要规则:**玻璃是透明的。**如果你无法阅读其背后的内容,那是 iOS 7 的磨砂玻璃,而不是 Liquid Glass。仅在文本位于玻璃上时才添加模糊和表面层。

诚实地告诉用户局限性在哪里。真实的材质仅存在于 iOS、iPadOS 和 macOS 26 及更高版本上;其他所有平台都是模仿。在 Android 上,Backdrop 库提供了完整的模拟(透镜效果需要 Android 13)。在 Web 上,折射效果仅在 Chromium 内核(Chrome、Edge、三星浏览器、Android WebView、Electron)上有效。Safari、Firefox 以及 iOS 上的所有浏览器会获得带有相同高光、阴影和弹性效果的轻度模糊,但不会有弯曲效果。

工作流程

  1. 识别平台。
    • iOS/macOS 26 上的 SwiftUI、UIKit、AppKit、WidgetKit:使用系统 API,参见 references/apple.md。不要模仿任何东西。
    • Jetpack Compose 或 Compose Multiplatform:references/android-compose.md。不要从头开始编写着色器,使用库。
    • Web、Electron、Android WebView、Capacitor、Cordova、Windows/Android 上的 Tauri:使用 assets/ 中的引擎,参见 references/web.md。在 WebView 和 Electron 中折射始终有效。
    • React Native、Flutter:没有系统等效方案。对于 React Native,建议使用 WebView 层或基于 Backdrop 的原生模块;对于 Flutter,BackdropFilter 作为后备方案,使用来自 references/math-and-motion.md 公式的 FragmentProgram。自行检查当前可用的包,此技能未列出它们。
  2. **选择控制层的 1 到 3 个元素:**标签栏、浮动按钮、顶部栏、工作表、菜单、开关或触摸时的滑块拇指。不要使内容变为玻璃。
  3. **从下表选择一个配方。**不要发明参数:这些值来自 Kyant 的目录并已在屏幕上验证。
  4. **检查玻璃下的背景。**玻璃仅在丰富内容上可见:照片、颜色、图表、滚动时的文本。在纯白页面上的透明玻璃几乎会消失:在其后方放置颜色、添加调暗层或移除该处的玻璃。
  5. 根据正确的参考构建并使用末尾的检查清单目视检查。未提供静态、按下和拖动状态截图前,不要交付。

苹果的规则

来自人机界面指南、WWDC25“Meet Liquid Glass”和流行的社区技能。违反其中任何一条都会立刻暴露是仿制品。

  • 仅限导航和控制层漂浮在内容之上。列表、行、卡片和页面背景不是玻璃。例外:触摸时,开关和滑块拇指变为玻璃。
  • **玻璃上无玻璃。**玻璃上的元素通过填充和不透明度进行区分。来自 Backdrop 的例外:玻璃工作表上的滑块拇指会折射工作表(exportedBackdrop):一个透镜叠加在另一个透镜上,而不是两个磨砂板。
  • **少量使用。**仅用于最重要的控件。
  • **玻璃是无色的。**颜色和亮度来自背景:浅色背景上为浅色,深色背景上为深色,高光由背景着色。没有自身的白色或灰色表面。
  • **两种模式,不要混合。**清晰(按钮、拇指、放大镜、与按钮组合的标签栏):模糊 0 到 4,无表面。常规(含有长文本的工作表、对话框):模糊 8 到 16;仅在无表面时文本不可读的情况下,添加 40% 到 60% 的表面。
  • 仅为主操作添加色调。
  • **形状。**胶囊形:半径等于高度的一半。同心圆角:内圆角半径等于容器半径减去内边距。
  • **越大越厚:**大元素获得更宽的弯曲边缘和更深的折射。
  • 切勿让内容一半位于玻璃下方。
  • **液态在运动中。**按下时,玻璃会增长几个像素并以阻尼方式向手指方向倾斜;拇指会膨胀 1.5 倍并以速度拉伸成水滴状。一切都在弹性运动上运行,没有线性过渡。

配方(来自 Kyant 目录的值)

元素效果高光和阴影触摸
按钮,48 dp 胶囊形活力,模糊 2,透镜(12, 24)默认,默认阴影发光;高度增加 4 dp;偏移 min × tanh(0.05 × offset / min);向手指方向拉伸最多 4 dp
有色调的按钮同上 + 色调同上同上
带表面的按钮同上 + 白色 30%同上同上
开关拇指 40×24,轨道 64×28静态:白色 100% 和模糊 8;按下 p:模糊 8(1−p),透镜(5p, 10p, 色散),白色 (1−p)环境,宽度 /1.5,alpha p;阴影半径 4,5%;内阴影半径 4p,alpha p缩放至 1.5;轨道通过透镜可见,缩小至 0.75
滑块拇指 40×24,轨道 6 dp像开关,透镜(10p, 14p)像开关缩放至 1.5;点击轨道会跳转至该点
标签栏 64 dp活力,模糊 8,透镜(24, 24),表面 #FAFAFA 40%(深色 #121212 40%)默认按下时整个面板宽度增加 16 dp(标签一起),并在手指后倾斜最多 4 dp
隐藏行副本 56 dp (tabsBackdrop)相同面板但使用强调色,alpha(0):活力,模糊 8,透镜(24p, 24p),面板表面默认带 alpha p,InteractiveHighlight按下时图标和标签放大 ×1.2(LocalLiquidBottomTabScale 仅在此行上设置)
标签栏拇指 56 dp静态:灰色 10%;按下:透镜(10p, 14p, 色散) 覆盖在背景和行副本之上(rememberCombinedBackdrop(backdrop, tabsBackdrop))默认,阴影和内阴影 8p 带 alpha p缩放 78/56;在水滴内部有一个“栏中之栏”:其自身项为强调色并放大,两侧的相邻项可见
对话框,半径 48亮度 0.2(浅色),饱和度 1.5,模糊 16(深色 8),透镜(24, 48, 深度)纯色背景变暗 #29293A 23%(深色 #121212 56%)
控制中心磁贴活力,透镜(24, 48, 深度)默认,角度来自设备倾斜,衰减 2进入:偏移 48 dp 和 alpha
放大镜 128×96透镜(8, 24, 深度, 色散),背景缩放 1.5x内阴影 16拖动

弹性运动、手势以及每个平台共享的数学原理都在 references/math-and-motion.md 中。

一分钟内搞定 Web 和 Android WebView

将 assets/ 中的三个文件原封不动复制到项目中,并使用选项进行配置。不要重写引擎。

<link rel="stylesheet" href="liquid-glass.css">
<button id="buy">购买</button>
<div id="wifi" aria-label="Wi-Fi"></div>
<div id="volume" style="width: 280px"></div>
<nav id="tabs" style="position: fixed; left: 16px; right: 16px; bottom: 16px"></nav>
<script src="liquid-glass.js"></script>
<script src="liquid-ui.js"></script>
<script>
  LiquidUI.button(document.getElementById('buy'), { tint: '#0088FF', onClick: () => {} });
  LiquidUI.toggle(document.getElementById('wifi'), { checked: true, onChange: (on) => {} });
  LiquidUI.slider(document.getElementById('volume'), { value: 0.4, onInput: (v) => {}, label: '音量' });
  const tabs = LiquidUI.tabs(document.getElementById('tabs'), {
    items: [{ label: '首页', icon: '<svg>…</svg>' }, { label: '搜索', icon: '<svg>…</svg>' }],
    index: 0, onChange: (i) => {},
  });
  // 融合:一个栏和一个相邻的按钮融合成一个水滴;相邻的弹性按钮会自动融合
  // LiquidUI.blob([tabs.panel, fab], { blur: 3.5 }); LiquidUI.autoMerge(document.body); 在屏幕变化后调用 LiquidUI.sweep()
  // 为您的自定义标记提供裸玻璃效果
  const g = LiquidGlass.attach(document.getElementById('panel'), { radius: 28, blur: 8, refractionHeight: 24, refractionAmount: 24, surface: 'rgb(250 250 250 / .4)' });
  // g.set({ lens: 0..1, blur, surface, highlightAlpha, angle, shadowAlpha, innerShadow, press: { p, x, y }, tx, ty, sx, sy, sleep })
</script>
文件说明
assets/liquid-glass.js玻璃引擎:折射映射、色散、高光、阴影、融合组 (LiquidGlass)
assets/liquid-glass.css基础样式、无障碍回退、组件样式
assets/liquid-ui.js弹性运动、手势和组件:按钮、开关、滑块、标签、放大镜、blob、autoMerge (LiquidUI)
assets/demo.html所有组件在单个页面中;打开它查看正确效果是什么样的

在修改任何内容或将其接入应用之前,请阅读 references/web.md:它列出了几乎会破坏所有实现的 Chromium 关键点(背景根元素、position: fixed、touch-action、body 背景)以及所有选项。当某些效果看起来不对时,请参考 references/troubleshooting.md;当出现卡顿时,请参考 references/performance.md。

Web 上绝不能出错的五件事:

  • 背景必须是一个真实的元素。设置在 body 上并传播到根元素的背景不会被 backdrop-filter 看到。
  • 切勿在玻璃的祖先元素上对 opacity、filter、mask 或 clip-path 进行动画(例如屏幕淡入):这会使其成为背景根元素,导致玻璃失去背景并变暗。使用 transform 移动屏幕,并使用顶部的遮罩层来显示它们。
  • 不要在玻璃元素上设置自己的 transform;将基础偏移写入 --lg-base。
  • 弹性按钮需要 touch-action: none(默认值)。使用 pan-y 时,浏览器会劫持拖动并发送 pointercancel。
  • 在 Android WebView 中禁用长按和触觉反馈:setOnLongClickListener(v -> true) 和 setHapticFeedbackEnabled(false)。

可访问性和可读性

  • Web 引擎遵循 prefers-reduced-transparency: reduce(关闭玻璃效果,使用几乎不透明的表面;Chrome 和 Edge 119+,Safari 或 Firefox 尚不支持)、prefers-contrast: more(实心表面和边框)以及 prefers-reduced-motion(弹性运动变为瞬时)。
  • 组件获得角色和键盘支持:按钮(Enter, Space)、switch(Enter, Space)、slider(方向键)、tablist(左、右方向键)。使用 aria-label 或 aria-labelledby 为它们添加标签。
  • 在 Android 上设置 semantics { role = Role.Switch } 和标签,如 Kyant 的目录中所示;在旧版 Android 上检查 onDrawSurface 颜色在没有效果的情况下是否可读。
  • 检查最亮和最繁忙内容上的文本对比度,这些内容可能最终位于面板下方:正文文本需要 4.5:1。如果失败,添加模糊和表面,或移动内容。文本阴影无法解决此问题。

不要做

  • 按钮上使用白色半透明表面加 blur(10px):那是磨砂玻璃,不是 Liquid Glass。仅在标签栏、工作表和要求文本的对话框上可以使用密度。
  • 使用玻璃内容卡片和玻璃页面背景。
  • 在大面板上使用色散:昂贵且俗气。
  • 使用粗白边框代替发丝般的高光线。
  • 每个按钮使用相同的色调。
  • 使用线性 transition 代替弹性运动来处理按下和拖动。
  • 在 Web 上对玻璃的 width 和 height 进行动画:映射会在每一帧重建。请对 scale 进行动画。
  • 在结果被多个步骤读取的过程中使用繁重的滤镜步骤(模糊、置换、卷积、形态):Chrome 会为每个分支计算一次,导致手机冻结。
  • 为了“美观”而自行绘制玻璃表面。只有包含文本的密集面板才需要表面。
  • 在 Backdrop 可用时编写自己的 Compose 着色器。
  • 在苹果平台之外使用 SF Symbols 和 Apple 徽标:其许可禁止这样做。请使用开源的图标集。
  • 将 Web 或 Android 的结果称为“官方 Liquid Glass”。它只是风格上的模仿。

交付前检查清单

在 2 倍缩放比例下查看截图,亲自检查:

  1. **静态时叠加在网格或文本上:**线条通过透明玻璃可见,在边缘处向中心拉拢,高光很细。在白色背景上,玻璃通过边缘阴影和投影与页面区分;在深色背景上,通过光照侧的一条亮线区分。
  2. **按下:**按钮增长并向手指方向倾斜;拇指膨胀且透明,轨道透过它可见,彩虹柔和,没有彩色空洞。
  3. **拖动:**拇指以速度拉伸,仅在到达后才收缩;标签栏倾斜并回位。标签栏水滴在边缘标签和靠近屏幕底部边缘处:其自身项在内,相邻项在边缘,没有黑色区域、条纹或镜像碎片。
  4. **拉动:**按钮跟随手指在橡皮筋上弹动并回弹;一个栏被拉向相邻按钮时会融合到其中,桥梁随着它们靠近而增长,没有接缝或双重边缘;在静态和简单按下时它们保持分离;正常点击有效,远距离拉动后释放的按钮不会触发。
  5. **叠加在照片和白色背景上:**玻璃下的色彩丰富,文本可读。
  6. 深色主题。
  7. **回退方案:**模拟引擎(Safari 用户代理和空的 navigator.userAgentData)并检查元素是否没有变成黑洞,标签栏拇指下的图标是否没有模糊。
  8. **缩放和旋转:**映射重建,边缘没有阶梯步骤。
  9. **屏幕过渡:**捕获屏幕进入时的连续几帧;玻璃按钮绝不会比静态时更暗,合并层在动画后精确地位于其按钮下方。
  10. 无控制台错误且无卡顿:在连续点击后页面响应速度如常。一个动画循环,没有多余的 requestAnimationFrame。
  11. 手机屏幕上不超过 3 个大玻璃元素,无玻璃上玻璃,无玻璃内容。

如果某个检查项失败,先修复它,然后再展示给用户。

来源

  • Kyant0/AndroidLiquidGlass、Backdrop 库和目录(Apache-2.0):透镜、色散、高光和阴影公式、组件配方、弹性运动和手势常量。Web 引擎是该方案的移植版本。
  • Apple:人机界面指南“Materials”、“Adopting Liquid Glass”、WWDC25“Meet Liquid Glass”。
  • kube.io,“Liquid Glass in the Browser”:通过 backdrop-filter 内的 feDisplacementMap 实现折射。
  • iyinchao/liquid-glass-studio(MIT):通过 smin 融合形状、Snell 折射、无色玻璃。

……

相关技能