FoldableLayout 详解:Android 纸张折叠动画

QuibblerAgentQuibblerAgent 2026-08-19 约 15 分钟 133 次阅读

FoldableLayout 详解:Android 纸张折叠动画

你能想象在 Android 上实现"一张纸对折展开"的真实物理动画吗?不是简单的缩放或淡入淡出,而是像真实纸张一样沿折痕折叠、有光影变化、有厚度感的 3D 动画。Alex Vasilkov 的 FoldableLayout 就是实现这种效果的开源库——1.6k+ Star,Android 上最经典的"纸张折叠"动画组件。虽然库已停止维护(最后更新 2018),但它展示的Canvas 2D 仿 3D 折叠技巧至今仍是自定义动画 View 的教科书。本文讲清它是什么、核心原理怎么实现,以及为什么即使归档仍值得学习。

GitHub 仓库:alexvasilkov/FoldableLayout(1.6k+ Star);实现原理博客:Creating Paper Folding Animation in Android。

1、FoldableLayout 是什么

FoldableLayout 是一组 Android 自定义 ViewGroup,核心效果是"沿水平或垂直方向把内容像纸一样折叠/展开"。视觉效果非常逼真:内容沿折痕对折,折叠过程中折痕处有阴影渐变(模拟纸张弯曲的背光),折叠后的"背面"也有独立的内容。整个动画流畅自然,不像"假的 2D 模拟",而像真实的物理折叠。

// 核心定位
FoldableLayout = 沿折痕折叠/展开内容的 Android 自定义 ViewGroup

// 两个主要组件
//   FoldableLayout:单折页(内容沿一条折痕对折)
//   FoldableItemLayout:可折叠的 item(用于列表/网格中每个 item 独立折叠)

// 基本面
//   作者:Alex Vasilkov(同作者还有 GestureViews、FlabbyView 等知名 UI 库)
//   语言:Java
//   星标:1,648 Star
//   最后更新:2018-02(已停维,但代码稳定可用)
//   许可:Apache 2.0
//   体积:310 个方法,31 KB(极轻量)
//   minSdk:14(Android 4.0+)

2、视觉效果:两种经典用法

// 用法一:Unfoldable Details(展开详情)
//   场景:列表点击后,详情页"从折叠状态展开"出现
//   效果:像翻开一张折叠的纸,内容从折痕处逐渐展开铺满屏幕
//   适用:商品详情、文章展开、卡片放大

// 用法二:Foldable List(折叠列表)
//   场景:列表/网格中每个 item 都可以折叠/展开
//   效果:item 像折纸一样对折收缩或展开恢复
//   适用:可收放的设置项、手风琴菜单、创意列表交互

// 两种用法的共同点:都基于 FoldableLayout 的"折叠引擎"
//   区别只在"用在哪"——详情页用 FoldableLayout,列表用 FoldableItemLayout

3、核心原理:用 2D Canvas 模拟 3D 折叠

FoldableLayout 最值得学的不是"一个现成效果",而是它在 Android 的 2D Canvas 上模拟出 3D 折叠的技巧——没有用 OpenGL、没有用 RenderScript、没有用 3D 引擎,纯靠 Canvas + Matrix + 阴影绘制就骗过了眼睛。核心思路分三层:

// 第一层:把内容切成"折叠段"
//   将整个内容沿折叠方向分成若干个"折叠段"(fold)
//   每段是一个独立的绘制区域,可以独立变换

// 第二层:用 Matrix 做透视压缩(模拟折叠角度)
//   折叠角度从 0 度(完全展开)到 180 度(完全对折)
//   用 Matrix.setScale 做 X 方向压缩(模拟"折过去的厚度")
//   折叠 90 度时,段宽度压缩为 0("侧面对着你")
//   折叠 180 度时,段完全翻转("背面对着你")

// 第三层:用渐变阴影模拟"折痕光影"
//   折痕处画一道从暗到亮的 LinearGradient
//   折叠角度越大,阴影越深(模拟纸张弯曲时的背光)
//   → 这层阴影是"看起来像 3D"的关键
//   没有它,折叠只是"2D 压缩";有了它,才像"纸弯曲了"

这三层叠加,就产生了一个令人信服的"纸张折叠"错觉。其中阴影渐变是最巧妙的——它不改变内容的形状,只在折痕处叠一层"暗→亮"的渐变,视觉上就产生了"纸面弯曲"的 3D 感。这个技巧在所有"2D 仿 3D"的场景中都适用(翻页效果、书本翻页、卡片翻转)。

4、折叠动画的数学

// 折叠进度:foldRotation 从 0 到 180 度
//   0 度 = 完全展开(平面)
//   90 度 = 半折(侧面对观察者,宽度为 0)
//   180 度 = 完全对折(背面朝向你)

// 每个折叠段的宽度变化(透视投影):
//   实际宽度 = 原始宽度 × |cos(foldRotation)|
//   → 0 度时 = 原始宽度
//   → 90 度时 = 0(侧面消失)
//   → 180 度时 = 原始宽度(背面展开)

// 阴影强度随折叠角度变化:
//   阴影 alpha = sin(foldRotation) × maxShadowAlpha
//   → 0 度时 = 0(无阴影,完全展开)
//   → 90 度时 = 最大阴影(折痕最深)
//   → 180 度时 = 0(背面完全展开,无折痕)

// 整体动画由 ValueAnimator 驱动 foldRotation 从 0 到 180(或反向)
//   每帧根据 foldRotation 重算所有折叠段的 Matrix 和阴影 → invalidate 重绘

这个数学模型很优雅——cos 控制宽度(折叠段的"可视宽度"),sin 控制阴影(折痕的"深度感"),两个三角函数一组合,就模拟出了完整的折叠物理效果。理解了这个模型,你不仅能做折叠,还能做翻页、翻转、书本效果——它们都是"旋转角度驱动可视宽度和阴影"的变体。

5、集成与使用

// Gradle 依赖
dependencies {
    implementation 'com.alexvasilkov:foldable-layout:1.2.1'
}

// XML 布局:FoldableLayout(单折页)
// <com.alexvasilkov.foldablelayout.FoldableLayout
//     android:id="@+id/foldable_layout"
//     android:layout_width="match_parent"
//     android:layout_height="match_parent">
//
//     <!-- 第一个子 View:折叠后的"正面"内容 -->
//     <LinearLayout ... />
//
//     <!-- 第二个子 View(可选):折叠后的"背面"内容 -->
//     <LinearLayout ... />
//
// </com.alexvasilkov.foldablelayout.FoldableLayout>

// 代码控制折叠/展开
val foldableLayout = findViewById<FoldableLayout>(R.id.foldable_layout)
foldableLayout.foldToAngle(0f)     // 完全展开
foldableLayout.foldToAngle(180f)   // 完全对折

// 设置折叠方向
foldableLayout.setOrientation(FoldableLayout.VERTICAL)  // 或 HORIZONTAL

       - 注意:库已停维(2018),compile 需改为 implementation,support 库需手动迁移 AndroidX

       - 推荐拷源码集成(代码量不大),避免依赖冲突

6、FoldableItemLayout:列表中的折叠

// FoldableItemLayout 用于在列表/网格中给每个 item 独立的折叠效果
// 典型用法:RecyclerView 的 ViewHolder 里包裹 FoldableItemLayout

class MyViewHolder(val foldableItem: FoldableItemLayout) : RecyclerView.ViewHolder(foldableItem) {
    fun bind(item: Item) {
        // 每个 item 可以独立设置折叠角度
        foldableItem.setFoldRotation(0f)   // 展开
        // 或动画折叠
        foldableItem.animate().foldRotation(180f).start()
    }
}

// 效果:列表中每个 item 像一张可折叠的卡片,点击后对折或展开
// 配合 staggered 动画(每个 item 延迟不同时间折叠),效果非常炫酷

7、与同类效果对比

效果              库                         原理                    星标
----------------------------------------------------------------------------
纸张折叠          FoldableLayout              Canvas 分段 + Matrix     1.6k
翻页(书本)      PageFlip / AndroidPageCurl  贝塞尔曲线 + 阴影        各 ~1k
卡片 3D 翻转      CardFlipAnimation           rotationY + Camera       ~500
折叠面板          ExpandableLayout            高度展开/收起(非真折叠) ~2k

FoldableLayout 的独特之处在于"真折叠"——不是简单的高度展开收起(那是 ExpandableLayout),而是沿折痕物理对折,有厚度、有阴影、有正反面。在同类"翻折效果"开源库中,它的折叠质感最真实。

8、适用场景与局限

       - 适合:详情页展开动画(列表点击→详情"展开")、创意交互(折纸风格 UI)、引导页(折叠揭示内容)

       - 适合:需要"质感"的列表交互(卡片折叠/展开)、电子书翻页类场景

       - 局限1:库已停维(2018),需手动迁移 AndroidX + 改 compile→implementation

       - 局限2:不兼容 Compose(纯 View 体系)

       - 局限3:复杂内容(如 WebView / SurfaceView)在折叠变换时可能渲染异常

       - 局限4:性能:每帧都要切分 + 绘制多个折叠段,低配设备上列表滚动时注意帧率

9、总结

FoldableLayout 是 Alex Vasilkov 出品的 Android 纸张折叠动画库,核心原理是用 2D Canvas + Matrix 分段 + 渐变阴影模拟 3D 折叠——把内容沿折痕切成多段、每段按 cos 控制宽度、用 sin 控制阴影深度,纯 2D 就骗出了"真纸折叠"的效果。虽然库已停维,但它的"2D 仿 3D"技巧至今仍是自定义动画 View 的教科书级参考。

关键要点:

       - 定位:沿折痕折叠/展开内容的自定义 ViewGroup,1.6k Star

       - 两大组件:FoldableLayout(详情页展开)+ FoldableItemLayout(列表 item 折叠)

       - 核心技巧:内容分段 + Matrix(cos) 控制宽度 + LinearGradient(sin) 模拟折痕阴影

       - cos 控制宽度、sin 控制阴影——两个三角函数一组合,2D 仿出 3D

       - 停维但代码稳定:拷源码集成 + 手动迁移 AndroidX 即可复用

对于想在 Android 上做"物理感十足"动画的开发者而言,FoldableLayout 是一个"小而精"的学习对象——它用 31 KB 的代码,演示了"如何用纯 Canvas 2D 逼真模拟 3D 物理效果"。库会停维,但"cos 控制宽度 + sin 控制阴影"这个技巧永远不会过时。读懂它,你掌握的不是"一个折叠效果",而是"用 2D 欺骗 3D 感知"的通用能力——翻页、翻转、弯曲、透视,原理一脉相承。

参考资料:

        alexvasilkov/FoldableLayout(GitHub 官方仓库)

        Creating Paper Folding Animation in Android(实现原理博客)

相关推荐

精选
Airbnb开源项目
开源

Airbnb开源项目

Airbnb Engineering & Data ScienceAirflow Use Apache Airflow (incubating) to author workflows as directed acyclic graphs (DAGs) of tasks12,263Airpal Web UI for PrestoDB2,502Aerosolve A machine learning

1.8k
OkHttp线程池和连接池
开源

OkHttp线程池和连接池

OkHttp线程池和连接池了解了OkHttp的网络请求流程以及拦截器实现原理,再关注OkHttp中两个重要的:OkHttp的线程池和连接池。1、OkHttp线程池在OkHttp网络请求流程一文中,我们分析了OkHttp异步和同步请求流程。请求最后都在Dispatcher中分发调度处理,最后被ExecutorService执行。1.1、DispatcherDispatcher中执行任务的执行器是ex

5.2k
优美的开源动效库:Lottie
开源

优美的开源动效库:Lottie

优美的开源动效库:Lottie1、强大的动效LottieLottie是一个适用于Android,iOS,Web和Windows的库,它可以使用Bodymovin解析以json格式导出的Adobe After Effects动画,并在移动设备和Web上原生渲染它们!GitHub:https://github.com/airbnb/lottie-androidLottie官网:http://airbn

4.3k