尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用堆栈和组件状态,把静态组件变成响应式UI活组件

用堆栈和组件状态,把静态组件变成响应式UI活组件 做 UI 设计这几年我最怕听到的一句话就是“这里再加一行文案”。表面只是一句话背后却是静态组件带来的连环噩梦卡片被撑高按钮要往下挪旁边几个画板里的同一张卡片全得手动改一遍。Adobe XD 里的“静态组件”说白了就是画板上摆好的一堆坐标固定的矩形和文本框改一个地方其他地方统统罢工。直到我把 XD 的堆栈Stack和组件状态Component States真正用进工作流才算是告别了这种“死”组件。这篇文章就聊聊我怎么用这两个功能把静态组件改造成会自动撑开、自动变脸、全局同步的“活”响应式 UI适合正在做界面设计、交互稿、以及想搞懂响应式设计原理的设计师参考。1. 为什么你的组件是“死”的静态组件背后的三个真相1.1 布局全靠手拖改一次要动全身大多数设计师在 Adobe XD 里做卡片、列表、导航栏的时候路径是这样的拉一个矩形当背景拖进一张图片打一段标题再放一个按钮然后用键盘方向键一点点把间距调成“看起来差不多”。这本质上是在做“绝对定位”每个元素的位置都是写死的坐标值。问题在于真实项目的文案和内容从来不会按你画稿时的大小乖乖待着。产品经理说“标题太长了换成文案 B”你辛辛苦苦对齐好的卡片就崩了——标题把高度顶开了下面本该相距 12px 的按钮却还留在原地图片和文字之间多出一块尴尬的空白。更崩溃的是这种卡片在这个页面里出现了 8 次跨了 5 个画板你就得手动重排 40 次。这就是静态组件的第一个真相它没有“弹性”可言所有的布局关系在按下 CtrlS 那一刻就焊死了。1.2 交互状态靠复制画板维护成本成倍放大静态组件的第二个问题出在交互状态上。以前做一个按钮的悬停、按下、禁用效果最原始的做法是复制出好几个按钮组件各自起名“按钮-hover”“按钮-pressed”“按钮-disabled”然后手动改颜色、改阴影。逻辑上是能跑通但工作量直接被状态数量翻倍。等你改版的时候才叫痛苦默认状态的按钮要改成圆角 8px那后面那几个复制出来的“状态副本”也得跟着一个一个改漏掉任何一个原型演示时就会被产品和开发同时指出“这里不一致”。做 UI 的人都明白这种零散的复制件一旦多起来设计文件就成了一团浆糊根本不敢动。1.3 传统组件解决了复用却没有解决自适应Adobe XD 很早就有组件功能可以把一组对象变成主组件再在页面里放实例。这个机制确实解决了“复用”的问题改主组件所有实例同步更新。但如果你仔细观察会发现它只是把“复制粘贴”升级成了“批量替换”实例在画板里的位置、大小、内部元素的排列关系依然是固定的。换句话说传统组件解决的是“多处出现同一张脸”但没解决“这张脸在不同内容下如何自己调整表情”。真正让组件“活”起来的是堆栈赋予的自适应布局能力加上组件状态赋予的多形态切换能力。这两个功能一个管空间一个管时间互补起来才算是把响应式 UI 的底座搭了出来。2. 堆栈Stack让元素自己学会“排兵布阵”2.1 堆栈是什么从手动对齐到自动布局第一次用堆栈的体验可以用“开了窍”来形容。它的操作非常简单选中你画板里的几个对象右侧属性面板里找到“Stack”按钮点下去XD 会自动把它们排列成一组有规律的布局。你可以一键切换水平排列或垂直排列并且任意调整对象之间的间距。这个能力其实有点像前端 Flexbox 的基本概念只不过对设计师来说完全不需要写代码用鼠标就能完成。我个人的理解是堆栈在元素之间建立了一种实时的“绑定关系”。你把文字改长同一列的元素会自动往下推你删掉中间一个图标后面的对象会自动补位你拖动整个堆栈的宽度内边的对象会根据约束自动伸展或收缩。这种“改一处、全联动”的反馈第一次看到时真的会有一种“组件活了”的感觉。需要注意的是堆栈不是简单的编组。编组只是把一堆对象放进一个文件夹里方便移动内部元素之间没有任何关系堆栈则是在编组的基础上加了一套排布算法让组内对象始终按照你设定的方向、间距、边距来排列。用久了你会发现编组慢慢就只用来做“收纳”了凡是需要参与布局的对象我几乎全部用堆栈来完成。2.2 堆栈的三大核心参数方向、间距、内边距堆栈看起来是个一键功能但真正要用好必须吃透它的三个核心参数。第一个是方向。水平堆栈适合做导航、按钮组、标签栏垂直堆栈适合做卡片内容、列表项、表单字段。实际项目里我大部分结构是垂直堆栈里嵌套水平堆栈比如一个典型的列表项左边是头像固定中间是两行文字垂直堆栈右边是操作按钮固定。外层用垂直堆栈保证高度自适应内部用水平堆栈保证对齐关系不出错。第二个是间距Gap也就是相邻对象之间的距离。以前手动排布的时候间距全靠眼睛糊现在有了参数可以把所有页面之间的同类间距统一成体系中的数值。我自己的习惯是基础间距用 8 的倍数紧凑界面用 4 或 8常规界面用 12 或 16卡片内容区经常用 16 到 24分组区块用 32。这样设计出来的响应式布局每个间距都有据可查给开发标注的时候也能直接给出全局变量级的数值几乎不用二次沟通。第三个是内边距Padding它在选中整个堆栈组时出现在属性面板里。内边距决定的是“堆栈容器”与内部对象之间的距离相当于给内容区域加了安全边界。以前做一个卡片文字和卡片边缘的距离得用另一个透明矩形占位来撑开现在直接用 Padding 就能实现。这个参数配合圆角和背景色可以一次性做出很完整的卡片外观。2.3 嵌套堆栈真正构建可复用的响应式结构单层堆栈只是入了个门拿来做按钮、标签这种简单元素够用但真实的 UI 界面几乎都是多层嵌套的。我做一个文章卡片最外层是垂直堆栈里面从上到下排了封面图、标题、摘要、作者信息和“阅读全文”按钮。其中“作者信息”又是一个水平堆栈里面是头像、昵称和时间“阅读全文”按钮本身又是一个水平堆栈由图标和文字组成。嵌套堆栈的威力在于当你把摘要文字加长最外层的垂直堆栈高度变高下面的按钮自动往下走当你把按钮文字从“阅读全文”改成“Read More”按钮内部的水平堆栈会自动调整宽度卡片也会跟着变化。整个过程不需要任何手动拖动完全是结构化的“自动布局”。做嵌套堆栈有个要点只对同一层级、有明确排列关系的对象“打堆”。不要在一个堆栈里塞入所有对象而是先想清楚页面结构把内容分组然后一层层往上套。一旦嵌套层次乱了后期修改的时候反而会被堆栈的自动规则限制住改起来比手动还痛苦。所以我的习惯是先画结构树再动手搭图层。3. 组件状态Component States同一个组件多副面孔3.1 组件状态的核心价值一份主组件N 个状态组件状态是在 Adobe XD 的组件体系上做的一次升级。以前想要表达按钮的不同交互状态得复制出好几份独立的组件各改各的现在你只需要在一个主组件内部创建多个状态比如默认、悬停、按下、禁用、聚焦。这些状态共享同一个组件结构只是属性不同。这个功能最直观的价值就是维护成本断崖式下降。改主组件里的圆角、字号、图标所有状态全部同步更新单独改某一个状态的颜色和阴影也只影响那一个状态。这意味着你既不需要为每个状态复制一份组件也不会因为改默认态而污染其他状态的差异。我更愿意把组件状态理解成一个组件的“分时复用”。同一个按钮鼠标没有碰到它时是一种长相悬停时换一个长相按下时再换一个长相——但它在组件面板里只有一个主组件在页面上也只有一个实例。原型演示的时候状态的切换让交互看起来有了真实反馈而不是一张张静态画板翻页。3.2 怎么给组件添加状态从默认到悬停按下禁用创建状态的方式很简单。选中一个已经做好的组件在右侧属性面板找到组件状态那一栏点“新增状态”的加号就会生成一个新的状态默认叫“State 2”。你可以给它重命名改成悬停、按下、禁用等等然后在这个状态里修改任意属性填充颜色、边框、阴影、文字内容、图层可见性等等。状态之间是“差异记录”机制这一点非常关键。你在“默认”状态里把按钮背景做成蓝色文字是白色切到“悬停”状态只把背景改成深蓝其他什么都不动那么两个状态就只在背景色这一条属性上有差异。后续如果统一改字号因为默认状态和悬停状态共享组件属性只改一处两个状态都会同步不会造成状态间越来越不同步的情况。状态切换的交互连线在“原型”面板里设置。选中组件的实例在右侧交互面板里选择触发方式比如鼠标悬停目标选同一个组件实例动作选“切换组件状态”然后指定要切换到的目标状态。这样一来进入预览模式后鼠标放上去按钮就会自动换成悬停外观点下去又会切到按下外观。3.3 状态不仅是“换肤”还能配合动效与逻辑组件状态的价值如果只用在换颜色上那就太浪费了。它最妙的地方是可以叠加智能动画状态之间只要图层结构保持一致XD 就能为颜色、位置、大小、透明度等属性自动生成平滑过渡。比如一个卡片默认是收起状态点一下切到展开状态展开状态里多显示了一段文字同时卡片因为堆栈的存在自动拉高——这个动作在预览时看起来就像真实前端组件的展开动画。组件状态还能做内容形态的切换。比如同一个双语卡片组件默认状态放中文文案另一个状态放英文文案交互触发时切换。由于堆栈在背后承担布局两种语言的文字长短不一样卡片也能自动适应不会出现英文内容溢出容器的尴尬。不过也要提个醒XD 的组件状态更适合做“交互控件”层面的状态切换如果你是想做整个页面的明暗主题切换它并不是主力方案。页面级的主题切换建议配合设计令牌、XD 的变量功能和插件来做把颜色值集中管理状态只用来承载具体控件的视觉变化。别硬把一个全局主题塞进某个局部组件的状态里那样维护起来会非常乱。4. 堆栈 状态组合实战做一张会“长高”的响应式卡片4.1 实战目标一张能自动伸缩、带交互反馈的卡片理论讲再多不落到实操总是不踏实。我们直接做一个最常见的场景一张文章卡片。默认状态下它显示封面图、标题、摘要和按钮鼠标悬停以后摘要文字变长、按钮换色同时整张卡片在堆栈的带动下自动“长高”一点点给新增内容腾出空间。这个效果听上去简单但用静态组件的老办法几乎没法做因为高度变了之后的布局全靠手动推。用堆栈加组件状态整个实现思路完全不一样卡片的高度我根本不去手动“定死”而是让它由内容自动撑开。卡片主容器是一个垂直堆栈从上到下依次排列图片、文字区、按钮区文字区又是一个垂直堆栈里面有标题、摘要文本。摘要文本在默认状态只有一行在悬停状态变成两行——堆栈会自动把下面所有内容往下推这就是卡片“活”起来的关键。4.2 从零到一的详细步骤搭建自动撑开的卡片结构第一步画卡片的基础结构。先在画板里拉一个圆角矩形作为卡片背景我给的建议是圆角 16宽度 360先不要定高度再拖入一张封面图、一个标题文本、一个摘要文本、一个按钮组件。这里注意背景矩形先别急着和内容打堆内容部分先单独成结构。第二步把文字区做成垂直堆栈。选中标题和摘要文本点击属性栏的 Stack方向选垂直间距设成 8。这样标题文字改多改少摘要都会自动往下退。接着把封面图、文字区、按钮一起选中再打一个垂直堆栈间距设成 16内边距根据卡片整体需求设成 20。这时候卡片的高度已经是“自动”的了你手动拉伸背景矩形反而会被内容带跑所以背景矩形在结构上我通常放在最外层单独用固定约束配合堆栈组来对齐。第三步把整个卡片结构嵌套成一个组件。选中背景矩形和内部堆栈右键“创建组件”主组件名可以叫“文章卡片”。组件创建好之后实例就具备挂载状态的能力了。第四步给组件添加状态。在组件状态面板里新建一个状态命名为“悬停”然后在这个状态下做两件事一是把摘要文本的内容改成更长的文案二是把按钮的背景颜色改深一点或加一个微妙的阴影。注意只改你希望变化的属性千万别在悬停状态里拖动元素的位置否则状态切换时会出现突兀的跳动。第五步把交互连起来。回到画板选中组件实例在原型面板添加交互触发方式选“鼠标悬停”动作选“切换组件状态”目标状态选“悬停”。预览一下悬停时摘要变长卡片自动撑高按钮颜色变化整个过程顺滑自然。因为堆栈参与布局悬停状态里文字即使比默认状态长出一倍卡片也不会出现文字溢出或者元素重叠的问题。4.3 界限明确状态解决内容切换变量解决全局主题做完上面这张卡片你可以试着扩展一下思路组件状态不仅做悬停也能做“展开/收起”。再新建一个“展开”状态把摘要文字改成完整长文图标方向转 180 度触发方式换成“点击”。这样同一个组件实例就同时具备了悬停反馈和点击展开两种交互能力而且每种形态都因为堆栈的存在而自动适配内容长度。如果你想把它推向明暗主题我的经验是不要直接用状态去改整个界面的背景和所有文字颜色。XD 的组件状态本质上还是跟着“组件实例”走的它管得住卡片自身管不住页面里所有游离的图层。真正要做主题化正确的姿势是先在 XD 里把颜色、圆角、间距这类设计令牌定义成变量再把卡片里的颜色引用全部替换成对应变量。这样暗色模式化的时候只需要切换变量的值所有引用过它的组件状态都会自动跟着变。我见过不少新人把状态功能当万能药硬拿它去做全局主题切换结果状态越加越多组件状态面板长到要滚动三屏最后自己都分不清哪个状态该在什么条件下显示。记住一句话堆栈管布局结构状态管交互形态变量管全局品牌三者各司其职才能把响应式 UI 做得既灵活又清爽。5. 常见问题与排查我踩过的那些坑5.1 堆栈按钮是灰的根本点不了这是我在最早接触 XD 堆栈时遇到的第一个问题选中好几个对象属性面板里的 Stack 按钮就是灰色禁用状态。后来排查发现最常见的原因是选中的对象里面有画板、符号旧版本的组件、或者是位图填充的非普通图形这些对象在特定条件下不参与堆栈创建。另外如果你选中了组件的实例堆栈按钮也会灰因为实例的布局规则由主组件决定不能直接在实例上另起一套堆栈。解决方法是先检查选中的图层面板层级确保你选的是普通图层。如果是在组件内部想打堆栈一定要双击进入主组件编辑模式再去选中内部对象。还有一个比较隐蔽的情况老版本 XD 里堆栈功能需要联网登录 Creative Cloud 账号才能使用离线状态下部分高级功能会变灰更新版本或重新登录就能解决。5.2 打好的堆栈间距怎么会出现“幽灵值”有时候明明已经把 Gap 设成 16视觉上对象之间的距离却忽大忽小尤其是包含文字对象的堆栈。这个问题的根源在于 XD 计算堆栈间距时依据的是每个对象的边界框。文字对象有一个特性它的边界框包含了行高带来的上下留白所以你目测的文字视觉间距比你设置的 Gap 要小或者大这是正常的。排查的时候可以先点选文字对象看它的选区边界是不是比文字本身“胖”了一圈。如果是可以适当调整文字的行高或者用“裁剪内容”的容器把文字的边界控制在更准确的范围里。另外也要检查是不是堆栈里夹带了透明占位矩形那种对象在画板上看不见但在图层面板里存在会把整体间距撑开某些情况下 Fabric 类工具也会有类似问题但 XD 里基本都出在隐藏对象和文字行高上。5.3 状态切换后智能动画不生效或者跳得很生硬组件状态配合智能动画做淡入淡出、平滑展开确实顺手但偶尔会遇到切状态时没有任何动画瞬间跳变。这个问题十有八九出在两个状态的图层结构不一致上。智能动画的原理是找到两个状态里“同名同层级”的对象然后对它们做插值如果你在悬停状态里删除了一个图层或者新加了一个默认状态里没有的图层XD 就没法为它生成中间帧。我的处理原则是状态之间只改属性不改结构。需要隐藏某个元素用图层眼睛图标关掉可见性而不要直接删掉需要新增内容提前在默认状态里就把对象放好并设成隐藏。这样切状态时所有对象都能被对上号动画自然就顺了。如果是颜色类动画不生效检查一下是不是两个状态里对象的填充类型不同比如一个用了纯色另一个用了渐变XD 在纯色和渐变之间插值的表现并不稳定尽量保持类型一致。5.4 组件状态在团队协作和跨文件复制时丢失团队协作时设计师 A 做好的带状态组件分享给设计师 BB 打开文件后发现交互状态全没了只剩一个普普通通的默认样式。这个情况多半是共享方式的锅。XD 的组件状态并不会自动跟随普通的“复制粘贴”在其他文档里完整保留需要以共享库CC Library的形式发布或者从“资源”面板里把主组件拖进目标文档。还有一个容易忽略的细节状态切换的交互连线保存在当前文当中如果你只是把主组件复制过去交互设置并不会跟着走。正确的流程是把组件发布到团队共享库目标文档从共享库插入实例然后重新连一次交互如果只是在本地文件之间搬运建议用“导出主组件”的方式把组件连同状态一起导出再在目标文档里导入这样至少能保住状态数据。把这条经验记录下来之后我在团队协作里很少再出现过组件状态丢失的情况。结尾堆栈和组件状态这两个功能刚上手时你会觉得它们只是在帮你省几次点击真正用进项目后才会意识到它们改变的是整个设计文件的组织方式和修改逻辑。有一点是肯定的从静态组件切换到堆栈加状态的组合会有一段不适应期最初的几张卡片可能要反复调整嵌套关系速度反而比以前慢。但坚持过前面两三个界面你会发现后续改版本、换文案、调状态整套流程会越来越像在操作一套有生命力的系统而不是在给一张不会呼吸的图“补丁再补丁”。最后再分享一个我自己的小习惯现在每做一个新组件我不再直接画完就拖进页面而是先想清楚这个组件哪些部分会变化哪些部分要保持稳定然后把稳定的部分用堆栈搭好把会变化的部分用组件状态预留出来哪怕当下还没人要求做悬停效果我也会先建好默认和悬停两个状态占位。这样做的好处是产品临时提需求时你只需改状态里的一条属性几十秒就能交付而不是重新拖一张画板。这套思路是你从“画图的”走向“做设计系统的人”的一个很实在的分水岭。
返回列表