)
MaterialKit核心秘密MKLayer涟漪效果实现原理深度剖析CAShapeLayerCore Animation全链路拆解【免费下载链接】MaterialKitMaterial design components for iOS written in Swift项目地址: https://gitcode.com/gh_mirrors/ma/MaterialKitMaterialKit 是一个用 Swift 编写的 iOS 物料设计Material Design组件库其中 MKLayer 是整个涟漪效果Ripple Effect的心脏——它基于 CAShapeLayer 与 Core Animation 构建了一套完整的波纹扩散动画系统。本文将深度拆解 MKLayer 涟漪效果的实现原理从三层图层架构、涟漪尺寸计算到触摸响应、动画编排与状态机带你完整看懂这条按下即波纹的全链路。一、MKLayer 是什么CALayer 的物料化升级MKLayer.swift 中MKLayer直接继承自CALayer而不是UIView子类。这是关键设计决策纯图层方案不引入视图层级不拦截手势不增加内存开销任何控件Button、TextField、TableViewCell都能挂载一个 MKLayer 来获得涟漪能力暴露可调参数rippleEnabled、rippleDuration默认 0.35s、rippleScaleRatio涟漪放大倍率、elevation悬浮高度等属性均可在外部直接配置组件的接入方式极其简单例如 MKButton.swift 里只需一行懒加载声明private lazy var mkLayer: MKLayer MKLayer(withView: self)之后把touchesBegan、touchesEnded等触摸事件转发给mkLayer按钮就拥有了物料风格的波纹反馈。二、核心架构三层 CAShapeLayer 的组合在 setup() 方法 中MKLayer 一口气创建了三个图层图层类型职责rippleLayerCAShapeLayer涟漪圆环本体负责缩放扩散动画backgroundLayerCAShapeLayer背景填充层按下时同步显示半透明底色maskLayerCAShapeLayer蒙版层保证涟漪不会溢出控件圆角边界三者都是CAShapeLayer而非普通 CALayer因为波纹本质是一个圆形路径UIBezierPath(ovalInRect:)需要靠path属性来定义形状。MKLayer 自身则通过mask maskLayer把整个子树裁剪在控件轮廓内——这就是涟漪只出现在按钮内部的秘密。同时setup()还对宿主图层注册了两个 KVO 观察观察bounds控件尺寸变化时自动重算涟漪大小观察cornerRadius圆角改变时同步更新蒙版路径这让涟漪效果能自动适配动态布局无需手动刷新。三、涟漪尺寸计算一个勾股定理波纹必须铺满整个控件无论控件是宽是窄。calculateRippleSize() 的解法非常优雅直径 √(宽² 高²) × rippleScaleRatio即控件对角线长度——以控件中心为圆心、对角线为直径的圆刚好能覆盖任意角落。随后rippleScaleRatio默认 1.0再整体缩放形成可配置的大小比例。let circleDiameter sqrt(powf(Float(superLayerWidth), 2) powf(Float(superLayerHeight), 2)) * Float(rippleScaleRatio)算出直径后代码把rippleLayer的 frame 居中摆放并写入圆形路径。backgroundLayer直接复用同一 frame 和 path保证两层严格同步。四、触摸响应涟漪从哪一点开始扩散当用户按下控件时事件流如下touchesBegan→ startEffects(atLocation:)若rippleEnabled为真 → startRippleEffect但波纹的起点有个细节触点可能落在控件边角如果直接用触点坐标圆环会偏心。nearestInnerPoint() 就做了一次几何回缩——若触点距中心的距离超过内切半径就把它沿径向等比拉回圆内确保波纹始终从可见区域内扩散视觉上更自然。双动画并行编排startRippleEffect中同时挂载了两个CABasicAnimation缩放动画transform.scale从 0 → 1配合 EaseIn 缓动圆环由点膨胀成满幅波纹位移动画position从触点坐标 → 控件中心让波纹被拉向中心两者共用rippleDuration默认 0.35s时长并行执行叠加出的运动轨迹正是物料设计中标志性的水波曲线。与此同时backgroundLayer立即显示半透明底色setRippleColor默认 0.3 透明度形成波纹 底色的双重反馈。五、状态机设计按下、松开与优雅退场MKLayer 用两个布尔标记userIsHolding与effectIsRunning维护一个轻量状态机覆盖三种场景松手stopEffects如果波纹动画还在跑通过重置timeOffset/beginTime/speed让动画快进到当前位置继续播放避免视觉跳变动画自然结束animationDidStop 回调中若用户仍按住则等待否则进入 clearEffects快速取消stopEffectsImmediately如滚动中断直接移除所有动画并复位透明度clearEffects的退场也很讲究它不会瞬间消失而是对 MKLayer 整体播放一段 0.3skMKClearEffectsDuration的 EaseInEaseOut 淡出动画且removedOnCompletion falsefillMode .forwards保证动画结束后透明度稳定归零。整个生命周期没有一次突兀的跳变。✨六、附加能力悬浮阴影Elevation物料设计的高度概念在 enableElevation() 中实现根据elevation属性动态设置宿主图层的shadowRadius elevation / 4并固定 0.5 的阴影不透明度。配合 KVO 对bounds的监听按钮抬起/按下的层级感都随布局实时更新。七、组件级复用一套涟漪全家共享MKLayer 作为基础设施被库里所有组件复用形成完整的物料体验矩阵MKButton.swift悬浮按钮/高亮按钮/扁平按钮支持IBInspectable在 Interface Builder 中实时调节rippleDuration、rippleLayerColor等MKTextField.swift涟漪 浮动占位符 下划线动画MKTableViewCell.swift列表行波纹反馈MKImageView.swift图片点击波纹可用于自定义 UIBarButtonItem对使用者而言只需一行赋值即可获得定制涟漪button.rippleLayerColor UIColor.MKColor.LightGreen button.rippleDuration 0.5总结值得学习的三个设计思想图层而非视图用CALayer子类做特效容器零侵入、可复用、不干扰手势几何驱动的动画对角线定直径、径向回缩定点、双动画并行编排——纯数学换来丝滑视觉状态机守护体验userIsHolding/effectIsRunning两个标记处理松手、取消、重按等所有边界情况这套不到 330 行的 MKLayer.swift堪称 iOS 端实现涟漪效果的经典范本。想动手实践完整可运行的示例工程位于 Example/ 目录配合 MaterialKit.podspec 即可通过 CocoaPods 引入库进行二次开发。【免费下载链接】MaterialKitMaterial design components for iOS written in Swift项目地址: https://gitcode.com/gh_mirrors/ma/MaterialKit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考