
简介面向Android等平台开发者的Material Design控件示例代码集依据官方设计规范整理帮助读者快速理解材料化界面中的层次、投影与动效语言并在真实项目中灵活复用这些组件。压缩包共52个文件以Java源码、XML布局和Gradle构建配置为主辅以少量资源图片与项目配置文件整体仅71KB轻量易用文件结构清晰适合直接导入工程或对照查阅。示例覆盖Button、FloatingActionButton、TextInputLayout、CardView、Snackbar、BottomNavigationView、BottomSheet、进度条、对话框、滑块、开关/复选框以及AppBar/Toolbar等常用控件几乎每一类都配有可直接运行的代码片段能直观看到按钮浮动、卡片阴影、底部弹层、输入标签等交互效果便于掌握属性设置与状态反馈。目前已有320人学习下载整体可作为一份离线速查手册既用于快速原型验证也能减少查官方文档和调试控件的时间尤其适合初中级开发者系统学习Material Design的实践要点。 这两年做客户端的同学应该都有个明显感受Material Design早就不再是“一组样式规范”那么简单了它已经长成了一整套从设计令牌到交互动效、再到跨端组件库的系统。而真正把项目从“原生感”拖到“精致感”的关键往往不是设计稿多漂亮而是对设计控件的掌握程度。这篇文章我打算用“控件的系统化认知 关键细节拆解 踩坑实录”的方式把我自己从照搬官方示例到能在实际项目里灵活组合控件的经验梳理一遍。适合刚接触 Material Design 的初级开发也适合那些已经写过不少界面、但总觉得交互反馈不“跟手”的朋友。1. 设计控件的理解方式先忘掉单个控件看整体交互语言很多新手入门 Material Design 会犯一个共同的错误一上来就盯着 Button、Card、Toolbar 逐个看属性。我可以直接说——这种学法效率很低而且做出来的界面往往是“形似神不似”。真正应该先建立的是三件事状态、层级、动效。1.1 状态是你最先要建立的意识Material 控件和其他 UI 框架最大的不同就是它对“状态”的刻画极其精细。一个按钮不只是“正常”和“点击”两种状态而是有 enabled、disabled、focused、pressed、hovered、dragged 这一整套状态容器。控件之所以显得“活”是因为每个状态都有对应的背景色调、透明度、高度变化。如果用一句话总结那就是控件不是静态的样子而是一组条件下可以组合呈现的反馈机制。理解了这一点你再看官方文档里的 state layer、elevation overlay 这些概念就会有一种“原来如此”的感觉。1.2 层级由高度和面积共同决定Material Design 里的“层级”主要由两个因素决定控件自身的面积大小以及它相对背景的高度偏移。高度偏移在 Android 里对应 elevation它是“物理阴影”的来源面积则决定了控件在视觉上的权重。在实际项目里我一般会根据功能优先级来确定控件的“体量”。主操作按钮用大号 Filled Button次要操作用 Outlined Button文字链接级别的操作用 Text Button——这不仅是美观问题也是引导用户注意力的手段。这个优先级思维比记住任何一条规范都更重要。1.3 动效不是装饰是空间关系的解释Material 的运动系统讲究的是“真实世界的惯性”控件从一个位置移动到另一个位置时要遵循加速、减速、回弹这些物理直觉。官方提供了标准曲线、加速曲线、减速曲线三种基础插值方式它们对应的是对象离场、入场、以及页面内移动的常见场景。动效在我眼里是成本收益比最高的部分。你哪怕只给 RecyclerView 的 item 加一个 200ms 的透明度渐入界面的精致程度都会上一个台阶。更具体的内容我会在第四节专门展开这里先建个概念动效空间切换的说明书。2. 核心控件的选型与配置从实际需求出发这一节咱们挑日常出镜率最高的几个控件用“场景→选型→关键参数”的思路来拆解。你会发现控件的很多属性如果不知道背后原因硬背是背不住的。2.1 按钮不要只会改颜色Material Design 的按钮家族大致分为三类强调主要操作的 Filled Button、用于次要操作的 Outlined Button、以及用于三级操作的 Text Button。三类按钮在视觉重量、点击区域、场景匹配上都不同。重点说两个常被忽略的配置一个是android:minHeight默认 48dp这个值直接决定了触控热区大小过小会影响手势体验另一个是图标与文字的组合方式MDC-Android 库提供了app:icon属性你不需要手动在布局里塞两个子控件直接设置这个属性会省掉大量的对齐问题。我给项目做按钮统一配置的经验是先把公共样式抽到styles.xml比如style nameWidget.App.FilledButton parentWidget.MaterialComponents.Button item namecornerRadius20dp/item item nameandroid:minHeight52dp/item item nameandroid:textSize14sp/item item nameiconTintcolor/white/item /style这样全局替换主题时只需要改一个地方不会出现二十个页面二十种按钮的失控场面。2.2 文本框容错设计才是体验的分水岭文本输入框TextInputLayout TextInputEditText是 Material 控件里最复杂的组件之一因为它承担了标签浮动、错误提示、密码可见性切换、字符计数等多重职责。我见到最多的失误是把 TextInputLayout 当成 FrameLayout 用只套了一个 EditText完全没发挥出它的能力。我在实际项目里的推荐组合是hint用app:hintEnabledtrue保持默认浮动效果但要注意加上android:paddingTop否则文字变大时容易遮挡。错误提示用app:errorEnabledtrue不要自己在下面再放一个 TextView 手动控制显示隐藏那个做法维护成本极高。密码输入框使用app:endIconModepassword_toggle图标和输入框内部绑定不用再写点击事件去切换InputType。如果表单校验失败你可以直接调用ilPassword.error 密码长度不足6位控件会自动处理颜色、图标、动画比自己手撸一套逻辑要省心得多。2.3 卡片圆角与高度有审美规律CardView 早先还是 support 库时代的产物现在 MDC-Android 的 MaterialCardView 提供了更多配置能力包括自定义描边、可点击状态下的按压反馈以及圆角大小设置。个人经验是圆角不是越大越好12dp 以上就接近“胶囊化”跟列表项的气质容易冲突。列表页里的卡片我一般用 8dp~12dp配合 1dp~2dp 的描边而不是一味依赖阴影这样的层次感在浅色背景下更干净。别忘了设置app:rippleColor与app:checkedIcon。如果你的卡片可点击没有涟漪反馈的话用户会觉得“点了没反应”这是交互心理层面的硬伤。2.4 AppBar 与 FAB页面框架的骨架AppBar 不只是放标题的容器还承担了返回导航、操作入口、以及滚动折叠的角色。MDC-Android 里推荐使用MaterialToolbar而不是旧版 Toolbar这样主题色、标题字体、溢出菜单样式会自动跟随全局配置。悬浮按钮FAB的选型主要看尺寸常规尺寸 56dp适合主操作小型 40dp适合辅助操作。它的位置我建议和列表内容的边距保持统一通常用layout_marginEnd16dp和layout_marginBottom16dp视觉上会更协调。如果页面滚动了想让 FAB 跟着消失或呈现配合第三节的布局联动下面会讲到。3. 主题、颜色与布局配合控件不能脱离上下文控件之所以难用很多时候不是控件本身的问题而是它所在的“上下文”没有搭对。这里的上下文指的就是主题和布局。3.1 主题是控件的总设计师Material Design 控件在 Android 上高度依赖Theme.MaterialComponents.*主题因为属性如colorPrimary、colorSecondary、colorSurface、colorOnPrimary等定义了控件从背景到文字的全部配色。一个建议所有颜色都通过主题属性间接引用不要在布局里直接硬编码色值。比如你的背景色需要调整你只需要改colorSurface整个应用里的卡片、对话框、输入框都会统一变化。硬编码会破坏这个体系。具体配置可以参考这个骨架style nameTheme.App parentTheme.MaterialComponents.Light.NoActionBar item namecolorPrimarycolor/primary/item item namecolorSecondarycolor/secondary/item item namecolorSurfacecolor/surface/item item namecolorOnPrimarycolor/white/item item namematerialButtonStylestyle/Widget.App.FilledButton/item item namematerialCardViewStylestyle/Widget.App.Card/item /style这样设置后你在 XML 里写Button它会自动匹配全局样式不需要每个页面单独指定。3.2 CoordinatorLayout 是联动的基础如果只用 FrameLayout 或 LinearLayout 做根布局你其实只发挥了 Material 控件六成的功力。很多“跟手”的交互比如 AppBar 滚动收起、FAB 随列表滚动隐藏/重现、底部弹层与列表的联动都需要CoordinatorLayout作为承载者。我之前做过一个详情页顶部是折叠视差头部中间是滚动内容右下角是 FAB。如果用常规写法要监听滚动事件再去改 FAB 透明度代码又臭又长改成CoordinatorLayoutAppBarLayoutCollapsingToolbarLayout后通过app:layout_behavior和app:layout_scrollFlags几个属性就完成了而且滑动动画是系统级跟手。3.3 暗黑模式与动态颜色从 Android 10 推出系统级深色模式后控件的“上下文”又多了一个维度。MDC 组件库对深色模式支持得不错只要你用主题属性引用颜色切换到深色模式时大部分控件能自动适配。如果你的应用要求自定义深浅色切换我建议在values-night目录里重新覆盖同一套颜色资源而不是为每个页面写两套布局。这样改动量最小也符合 Material 官方推荐的“通过语义化颜色资产驱动主题切换”的思路。4. 动效细节与手势反馈把“规范”变成“体验”很多开发者做到上一步就觉得界面“差不多能看”了但真正精致的应用往往胜在动效与反馈这些细微之处。4.1 控件状态切换的动画时长MDC 控件默认内置了状态切换动画比如按钮从普通态变按压态时高度与背景色都有一个渐变的过渡。如果你觉得默认动画不明显可以通过attr/stateLayerColor和colorControlHighlight来微调涟漪颜色与透明度。经验数值是按压反馈的动画时长控制在 100ms~200ms 之间太长会显得拖沓太短则感知不到。比如rippleColor的透明度正常态用 8%~12%按压态用 16%~24%视觉上刚刚好。4.2 进场动效列表与卡片列表项的进场动画是最容易出效果的。我常用的是 RecyclerView 默认的DefaultItemAnimator但如果你想让每个 item 之间有微小的“错峰”效果可以自定义 Animator 为每个 item 设置不同延迟。要注意一点这种动画不要应用到所有界面。频繁进出的场景、列表项特别多的情况下逐项动画会让用户反而感到“卡”。只在核心详情页、首屏卡片等地方使用效果最好。4.3 支持手势与触觉反馈Material Design 的交互反馈不只是视觉变化还有触觉。MDC 的按钮默认支持触觉反馈Haptic Feedback在 Android 10 及以上的设备上会有微弱的震动。如果你的业务有硬性需求比如长按按钮触发特殊操作可以结合View.performHapticFeedback做强化反馈比只弹 Toast 要自然很多。5. 常见问题与排查思路我用血泪踩出来的坑这部分记录我实际开发中的高频问题和排查过程分享出来是为了帮你避开这些成本极高的坑。5.1 控件换了个主题颜色还是不变这个问题通常是因为你在老版本主题如Theme.AppCompat里使用 Material 控件。MDC 组件库的主题要求规定必须用Theme.MaterialComponents或Theme.Material3家族作为基础主题否则控件的样式引用无法生效。排查方案很简单全局搜索parentTheme.AppCompat改成parentTheme.MaterialComponents.Light.NoActionBar或更高版本的基础主题然后再看控件样式是否恢复。5.2 TextInputLayout 输入框的底部指示线不见了部分机型上会出现输入框底部指示线显示异常的问题大多是因为给 EditText 单独设置了android:background。在 Material 设计体系里输入框的下划线由TextInputLayout内部的BoxBackground控制你手动设置背景会把这条线覆盖掉。解决办法是删除 EditText 上的背景设置改为使用app:boxBackgroundModeoutline或app:boxBackgroundModefilled再把颜色交给主题去管。5.3 阴影在部分设备上显示过重或没阴影elevation阴影在不同硬件、不同 Android 版本上表现差异很大。某些国产 ROM 会关闭或弱化阴影效果导致设计稿里预期的层级感出不来。如果你对层级显示要求高可以用outlineSpotShadowColor和outlineAmbientShadowColor微调阴影颜色或者用描边浅色面的方式来模拟层次。注意这种方式只在静态界面有效动态高度变化仍然需要依靠立体阴影。5.4 RecyclerView 刷新时卡片闪烁或状态丢失如果你给卡片设置了checkable或checkedIcon刷新列表时状态很容易被 RecyclerView 复用机制搞乱。根本原因是 item 复用时控件状态未重置。我在项目里的统一处理是在onBindViewHolder里强制重置状态比如holder.binding.card.isChecked false再根据数据设置正确状态。千万不要依赖控件的默认状态因为复用机制不会帮你“还原”默认。6. 一点真正想说的话控件的终点不是“用对”而是“克制”把所有 Material 控件都堆在页面上并不能让应用更好看。我自己的体会是刚开始接触这套体系时看到什么控件都觉得“高级”测出来页面上全是卡片、按钮、悬浮球交互反馈又多又密。后来回头删掉一半元素界面反而清爽了很多。如果你所在的项目已经接近交付阶段需要做界面统一性体检我建议按这个顺序检查一遍主题颜色是否有硬编码、按钮是否符合主次关系、文本输入框是否用原生错误提示、列表滚动与 FAB 是否联动、暗黑模式下是否有对比度异常。这些细节不显眼但用户能感知到。控件只是材料设计意图才是建筑。希望这篇内容能让你在下次拿到设计稿时不只是“找控件”而是能自然地思考——这里为什么需要这个控件它的状态该如何变化它和周围的空间怎样建立联系。想清楚这些问题做出来的东西就自带 Material 的质感了。本文还有配套的精品资源点击获取