YCBlogs 动画实践:Android 揭露动画(Circular Reveal)从 API 详解到实战落地 教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载导读本文基于 YCBlogs 仓库 android/16.动画实践/11.揭露动画实践详解.md 展开系统讲解 Android 5.0API 21引入的揭露动画Circular Reveal——一种以圆心为轴点、圆形区域向外扩散或向内收拢的 Material Design 视觉动效。读完本文你将掌握ViewAnimationUtils.createCircularReveal()五个参数的准确含义、View 显示与隐藏两种动画方向的完整代码写法以及动画回调时序中的关键坑点可直接将其落地到 Activity 内的 View 动效与 Activity 转场过渡动画中。1. 揭露动画概述从一点向四周扩散的波纹揭露动画Reveal Animation是 Android 5.0Lollipop及更高版本中新增的一种视觉动画效果它与同期引入的 Ripple 触摸反馈动画同属 Material Design 动效体系。揭露动画在系统中的表现类似波纹效果从一个点向四周展开或者从四周向某一点聚合本质是通过圆形裁剪区域clipping的动态变化来揭露或隐藏视图内容。它有两个典型的应用场景Activity 内部的 View 动画例如点击一个 FloatingActionButtonFAB从按钮圆心开始扩散把某个内容面板揭露出来Activity 跳转过渡动画配合 5.0 的 Transition 转场框架实现两个页面切换时的圆形展开效果。补充关于 Ripple 触摸反馈?android:attr/selectableItemBackground与自定义rippleDrawable的详细用法可参阅同目录下的 12.Ripple触摸反馈动画.md关于 Activity 转场与共享元素动画可参阅 06.转场动画基础详解.md。2. 核心 APIViewAnimationUtils.createCircularReveal()使用揭露动画非常简单Android SDK 已经提供了现成的工具类ViewAnimationUtils它内部只有一个静态方法用于创建揭露动画对象public final class ViewAnimationUtils { private ViewAnimationUtils() {} /** * ...... * param view The View will be clipped to the animating circle. * param centerX The x coordinate of the center of the animating circle, relative to * codeview/code. * param centerY The y coordinate of the center of the animating circle, relative to * codeview/code. * param startRadius The starting radius of the animating circle. * param endRadius The ending radius of the animating circle. */ public static Animator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) { return new RevealAnimator(view, centerX, centerY, startRadius, endRadius); } }createCircularReveal()方法为视图添加一个圆形裁剪区域并给该裁剪区域附加动画从而揭露或隐藏视图。五个参数含义如下参数类型含义viewView执行揭露动画的 View 视图动画期间该视图会被裁剪到动画圆内centerXint动画圆心的 X 坐标相对于 view 自身的坐标系centerYint动画圆心的 Y 坐标相对于 view 自身的坐标系startRadiusfloat动画圆的起始半径endRadiusfloat动画圆的结束半径从源码签名可以看到该方法返回一个RevealAnimator它是Animator的子类。从仓库 04.属性动画基础详解.md 对Animator体系的梳理可以推断RevealAnimator同样遵循属性动画的时间插值模型动画过程由系统在 UI 线程按帧驱动动画时长默认由setDuration()指定。因此揭露动画可以和普通属性动画一样设置时长、插值器与监听器。2.1 揭露动画的两种效果显示与隐藏揭露动画有两种截然相反的效果区别只在于起始半径与结束半径的大小关系显示一组 UI 元素以中心点为轴点startRadius endRadius动画从起始半径向外扩大到结束半径圆形裁剪区域由小变大视图内容随之被逐渐揭露出来隐藏一组 UI 元素以中心点为轴点startRadius endRadius动画从起始半径向内缩小到结束半径圆形裁剪区域由大变小视图内容随之逐渐收敛隐藏。3. 使用注意事项必须牢记的三个约束原文档特别强调揭露动画在使用上有三个与普通属性动画不同的约束动画对象只能使用一次RevealAnimator不能被复用每次使用都必须重新调用ViewAnimationUtils.createCircularReveal()创建新的动画对象。动画一旦开始不能暂停也不能重新开始异步执行揭露动画是异步动画可以自动运行在 UI 线程上不需要额外手动切换到主线程回调可能延迟当动画结束后如果设置了Animator.AnimatorListener监听器onAnimationEnd(Animator)方法会被调用但可能被延迟调用具体取决于线程的响应能力。这一点在下面的实战案例中会直接影响到代码的写法。4. 实战从 FAB 扩散揭露/隐藏一个 View原文档通过一个实例完整演示了揭露动画的具体用法。整个实践的核心只有一件事确定createCircularReveal()的四个参数圆心 X/Y、起始半径、结束半径。4.1 确定圆心坐标第 2、3 个参数动画圆心一般取触发控件如 FAB的中心点通过getLocationInWindow()获取控件在窗口中的位置再叠加上控件自身宽高的一半// 求出第2个和第3个参数动画圆心坐标 int[] vLocation new int[2]; fab.getLocationInWindow(vLocation); int centerX vLocation[0] fab.getWidth() / 2; int centerY vLocation[1] fab.getHeight() / 2;这里得到的centerX / centerY是相对于执行动画的 ViewmPuppet坐标系的坐标与 API 文档中relative to view的定义保持一致。如果圆心相对目标 View 不居中直接按需取 View 上任意一点即可。4.2 确定最大半径第 4、5 个参数的依据为了让圆形扩散能完整覆盖整个目标 View通常取目标 View 的对角线长度作为扩散圆的最大半径。利用Math.hypot()直接计算宽高的斜边长度// 求出要揭露 View 的对角线作为扩散圆的最大半径 int hypotenuse (int) Math.hypot(mPuppet.getWidth(), mPuppet.getHeight());Math.hypot(w, h)等价于sqrt(w² h²)即 View 的对角线长度。以对角线为最大半径可以保证无论圆心位于 View 内部哪个位置圆形裁剪区域最终都能覆盖整个 View。4.3 完整代码隐藏与显示fab.setOnClickListener(... { launchRevealAnimation(); }); private void launchRevealAnimation() { // 求出第2个和第3个参数动画圆心 int[] vLocation new int[2]; fab.getLocationInWindow(vLocation); int centerX vLocation[0] fab.getWidth() / 2; int centerY vLocation[1] fab.getHeight() / 2; // 求出要揭露 View 的对角线作为扩散圆的最大半径 int hypotenuse (int) Math.hypot(mPuppet.getWidth(), mPuppet.getHeight()); if (flag) {//隐藏 揭露对象 Animator circularReveal ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, hypotenuse, 0); circularReveal.setDuration(2000); circularReveal.addListener(new Animator.AnimatorListener() { Override public void onAnimationStart(Animator animation) {} Override public void onAnimationEnd(Animator animation) { mPuppet.setVisibility(View.GONE); } Override public void onAnimationCancel(Animator animation) {} Override public void onAnimationRepeat(Animator animation) {} }); circularReveal.start(); flag false; } else {//显示 揭露对象 Animator circularReveal ViewAnimationUtils.createCircularReveal(mPuppet, centerX, centerY, 0, hypotenuse); circularReveal.setDuration(2000); //注意这里显示 mPuppet 并没有在监听方法里并且是在动画开始前调用。 mPuppet.setVisibility(View.VISIBLE); circularReveal.start(); flag true; } }代码逻辑拆解隐藏分支startRadius hypotenuse最大、endRadius 0圆形从大收拢到小。由于动画过程中 View 仍然是可见的所以只需在onAnimationEnd回调里把 View 设为View.GONE动画结束后视图自然消失显示分支startRadius 0、endRadius hypotenuse圆形从小扩散到大。注意mPuppet.setVisibility(View.VISIBLE)的调用位置——它既不在onAnimationStart里也不在onAnimationEnd里而是在start()之前直接调用。4.4 关键坑点为什么显示 View 必须在动画开始前 setVisibility(VISIBLE)原文档作者特别指出这里栽过这个坑好久原因是必须先显示、后动画如果动画开始时目标 View 处于隐藏状态GONE/INVISIBLE动画虽然执行了但隐藏状态是看不到任何效果的。因此绝不能在onAnimationEnd回调里才设置View.VISIBLE——那时动画已经结束用户什么都看不到为什么不放在onAnimationStart回调里在动画开始的回调里设置View.VISIBLE也能工作一般不会出问题。但由于揭露动画是异步动画它的回调方法不能保证在准确的时间点被调用可能被短暂延迟。为了稳妥建议直接在调用start()之前设置View.VISIBLE这样能确保动画第一帧开始时视图就已经处于可见状态圆形扩散的每一帧都能被完整看到。这个时序问题同样适用于其他依赖监听回调做状态切换的动画场景凡是动画开始时就需要具备的视图状态都应尽量在start()之前设置好而不是依赖异步回调。5. 源码级延伸RevealAnimator 与属性动画体系从仓库 04.属性动画基础详解.md 可知Animator是 Android 所有属性动画的抽象基类其体系包含ValueAnimator、ObjectAnimator、AnimatorSet等子类。结合ViewAnimationUtils的源码可以推断揭露动画的底层实现RevealAnimator也属于该体系——它负责在动画过程中按时间插值动态改变圆形裁剪半径从而驱动 View 的揭露/隐藏效果。这意味着揭露动画天然具备属性动画的通用能力时长控制setDuration(2000)设置 2 秒动画时长监听器addListener(Animator.AnimatorListener)监听动画的 Start / End / Cancel / Repeat 四个生命周期回调插值器可以像普通属性动画一样设置Interpolator来改变动画速率曲线如加速、减速、回弹等从而微调波纹扩散的节奏感。注意揭露动画对象不可复用每次执行都要重新createCircularReveal()这与普通ValueAnimator通过start()重复执行的用法不同是它的独有约束。6. 进阶应用Activity 转场过渡与兼容性处理6.1 在 Activity 转场中应用原文档指出揭露动画除了用在 Activity 内部的 View 上也可以用在Activity 跳转过渡动画中。在 5.0 的 Transition 转场框架中可以把揭露动画与场景变换组合实现页面切换时目标界面从某个触点圆形展开的视觉连贯效果。关于 Transition 框架中场景Scenes与变换Transitions的核心概念可继续阅读 06.转场动画基础详解.md 和 07.Activity转场动画实践.md。6.2 版本兼容性说明揭露动画 API 从Android 5.0API 21开始提供在此版本以下的系统上直接调用ViewAnimationUtils.createCircularReveal()会因类不存在而崩溃低版本兼容方案一般是在调用前做Build.VERSION.SDK_INT 21的版本判断版本不足时退化为直接setVisibility()的普通显示/隐藏不播放动画此限制同样适用于同系列 Material 动效如 Ripple 波纹在 5.0 以下会退化为高亮显示详见 12.Ripple触摸反馈动画.md。7. 小结揭露动画的使用要点可归纳为一句话确定createCircularReveal(view, centerX, centerY, startRadius, endRadius)的五个参数牢记隐藏时在 onAnimationEnd 设 GONE、显示时在 start() 前设 VISIBLE、动画对象不可复用三条纪律。它适用于 5.0 及以上系统的 View 展示/隐藏动效与 Activity 转场过渡是实现 Material Design 风格界面动效的轻量级方案。本仓库动画实践系列还收录了帧动画、补间动画、属性动画、ViewPropertyAnimator、转场动画、视图状态动画等专题可参考 android/16.动画实践 目录继续深入全部博客笔记的索引见 blog/02.Android博客大汇总.md。赞分享教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载相关推荐Splink核心功能全解析多SQL后端支持如何实现跨平台数据关联Splink核心功能全解析多SQL后端支持如何实现跨平台数据关联 Splink是一款强大的概率数据关联工具通过多SQL后端支持实现跨平台数据关联帮助用户快数据分析数据工程YCBlogs 动画实践Android 转场动画Transition基础详解——场景、变换与共享元素YCBlogs 动画实践Android 转场动画Transition基础详解——场景、变换与共享元素 本篇技术指南围绕 Android 5.0 引入的 T教程技术博客文档ESP-IDF BluFi 蓝牙配网指南无屏设备如何安全拿到 Wi-Fi 密码ESP IDF BluFi 蓝牙配网指南无屏设备如何安全拿到 Wi Fi 密码 ESP IDF 内置了一个叫 BluFi 的配网方案手机把 Wi Fi 的教程技术博客文档上一篇用 LLM 当裁判基于 Agent Skills for Context Engineering 构建生产级 LLM-as-a-Judge 评估技能下一篇Ingress NGINX Controller 适配 JWT 认证调整 proxy-buffer-size 解决大请求头 502 错误实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考