FloatingView源码解析:从FloatingBuilder到动画执行的完整流程
【免费下载链接】FloatingViewFloatingView can make the target view floating above the anchor view with cool animation项目地址: https://gitcode.com/gh_mirrors/fl/FloatingView
你是否曾经想要在Android应用中实现酷炫的漂浮动画效果?FloatingView是一个强大的Android漂浮动画库,能够让你的视图在锚点视图上方以酷炫的动画效果漂浮起来。本文将从源码层面深入解析FloatingView的实现机制,带你了解从FloatingBuilder构建动画参数到最终动画执行的完整流程。😊
FloatingView的核心功能是通过简单的API让任何视图实现漂浮动画效果。无论是点赞动画、分享动画还是其他需要视觉反馈的场景,FloatingView都能轻松应对。让我们一起来看看这个优雅的动画库是如何实现的!
架构设计概览
FloatingView采用了经典的建造者模式(Builder Pattern)和策略模式(Strategy Pattern)相结合的设计。整个架构分为三个主要层次:
- 配置层:FloatingBuilder负责构建动画参数
- 容器层:Floating负责管理动画视图和生命周期
- 动画层:各种Transition实现具体的动画效果
从上图可以看出,FloatingView的核心类结构非常清晰。FloatingBuilder通过链式调用构建FloatingElement,Floating负责将目标视图添加到悬浮层并执行动画,而具体的动画效果则由实现了FloatingTransition接口的类来实现。
核心组件深度解析
1. FloatingBuilder建造者模式实现
在FloatingViewLib/src/main/java/com/ufreedom/floatingview/FloatingBuilder.java中,我们看到一个典型的建造者模式实现:
public class FloatingBuilder { private FloatingElement mFloatingElement; public FloatingBuilder() { mFloatingElement = new FloatingElement(); mFloatingElement.targetViewLayoutResId = -1; } public FloatingBuilder offsetX(int offsetX) { mFloatingElement.offsetX = offsetX; return this; } public FloatingBuilder offsetY(int offsetY) { mFloatingElement.offsetY = offsetY; return this; } public FloatingBuilder floatingTransition(FloatingTransition floatingTransition) { mFloatingElement.floatingTransition = floatingTransition; return this; } public FloatingBuilder anchorView(View view){ mFloatingElement.anchorView = view; return this; } public FloatingBuilder targetView(View view) { mFloatingElement.targetView = view; return this; } public FloatingBuilder targetView(@LayoutRes int layResId) { mFloatingElement.targetViewLayoutResId = layResId; return this; } public FloatingElement build() { // 参数校验和默认值设置 if (mFloatingElement.floatingTransition == null) { mFloatingElement.floatingTransition = new ScaleFloatingTransition(); } return mFloatingElement; } }FloatingBuilder采用了经典的链式调用设计,每个设置方法都返回this,使得代码更加流畅易读。在build()方法中,库还提供了默认的动画效果(ScaleFloatingTransition),这体现了良好的API设计原则。
2. Floating容器类的精妙设计
Floating类在FloatingViewLib/src/main/java/com/ufreedom/floatingview/Floating.java中实现,是整个动画系统的核心容器。它的主要职责包括:
- 创建和管理悬浮装饰视图:通过FloatingDecorView将目标视图添加到Activity的根布局中
- 坐标计算和定位:计算目标视图相对于锚点视图的位置
- 动画启动:调用具体的动画实现
public void startFloating(FloatingElement floatingElement) { View anchorView = floatingElement.anchorView; View targetView = floatingElement.targetView; // 如果targetView为空,则通过布局资源ID创建 if (targetView == null){ targetView = LayoutInflater.from(anchorView.getContext()) .inflate(floatingElement.targetViewLayoutResId,mFloatingDecorView,false); } // 计算锚点视图的全局位置 Rect rect = new Rect(); anchorView.getGlobalVisibleRect(rect); int[] location = new int[2]; mFloatingDecorView.getLocationOnScreen(location); rect.offset(-location[0], -location[1]); // 测量目标视图 int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST); int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) - 1, View.MeasureSpec.AT_MOST); targetView.measure(widthMeasureSpec,heightMeasureSpec); // 计算最终位置 int topMargin = rect.top + ((anchorView.getMeasuredHeight() - targetView.getMeasuredHeight()) / 2) + floatingElement.offsetY; int leftMargin = rect.left + ((anchorView.getMeasuredWidth() - targetView.getMeasuredWidth()) / 2) + floatingElement.offsetX; // 添加到悬浮层 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); lp.topMargin = topMargin; lp.leftMargin = leftMargin; mFloatingDecorView.addView(targetView,lp); // 执行动画 FloatingTransition floatingAnimator = floatingElement.floatingTransition; floatingAnimator.applyFloating(new YumFloating(targetView, mSpringSystem)); }这段代码展示了FloatingView如何精确计算目标视图的位置。通过getGlobalVisibleRect()获取锚点视图的全局坐标,然后根据悬浮装饰视图的位置进行偏移,确保目标视图能够准确地显示在锚点视图上方。
3. 动画系统设计
FloatingView的动画系统采用了策略模式,通过FloatingTransition接口定义了统一的动画执行方法:
public interface FloatingTransition { public void applyFloating(YumFloating yumFloating); }这个简单的接口设计使得动画效果可以轻松扩展。让我们看看几个具体的动画实现:
ScaleFloatingTransition缩放动画
在FloatingViewLib/src/main/java/com/ufreedom/floatingview/effect/ScaleFloatingTransition.java中:
public class ScaleFloatingTransition implements FloatingTransition { @Override public void applyFloating(final YumFloating yumFloating) { // 透明度动画 ValueAnimator alphaAnimator = ObjectAnimator.ofFloat(1.0f, 0.0f); alphaAnimator.setDuration(mDuration); alphaAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { yumFloating.setAlpha((Float) valueAnimator.getAnimatedValue()); } }); alphaAnimator.start(); // 缩放动画(使用Facebook Rebound物理引擎) SpringHelper.createWithBouncinessAndSpeed(0.0f, 1.0f, mBounciness, mSpeed) .reboundListener(new SimpleReboundListener(){ @Override public void onReboundUpdate(double currentValue) { yumFloating.setScaleX((float) currentValue); yumFloating.setScaleY((float) currentValue); } }).start(yumFloating); } }ScaleFloatingTransition结合了Android原生的ValueAnimator和Facebook的Rebound物理引擎,创建了既有流畅性又有物理感的动画效果。
路径动画实现
对于更复杂的路径动画,FloatingView提供了BaseFloatingPathTransition基类。让我们看看路径动画的关键实现:
public abstract class BaseFloatingPathTransition implements FloatingPathTransition { public PathPosition getFloatingPosition(float progress) { if (mPathPosition == null){ mPathPosition = new PathPosition(); } if (mPathPositionGetter == null){ mPathPositionGetter = new float[2]; } if (getFloatingPath() != null){ // 获取路径上指定进度的坐标 getFloatingPath().getPathMeasure().getPosTan(progress, mPathPositionGetter, null); mPathPosition.x = mPathPositionGetter[0]; mPathPosition.y = mPathPositionGetter[1]; } return mPathPosition; } }这个基类使用了Android的PathMeasure类来精确计算路径上任意点的坐标,为自定义路径动画提供了坚实的基础。
4. YumFloating视图包装器
YumFloating类在FloatingViewLib/src/main/java/com/ufreedom/floatingview/transition/YumFloating.java中定义,它起到了桥梁作用:
- 视图操作代理:将动画属性应用到实际的目标视图
- 物理引擎集成:封装了Facebook Rebound物理引擎的创建和使用
- 资源管理:提供clear()方法清理视图资源
public class YumFloating implements ITransition, Rebound { private WeakReference<View> mTargetViewWeakReference; public void setAlpha(float alpha) { View targetView; if ((targetView = getTargetView()) != null){ targetView.setAlpha(alpha); } } public Spring createSpringByBouncinessAndSpeed(double bounciness, double speed) { return mSpringSystem.createSpring() .setSpringConfig(SpringConfig.fromBouncinessAndSpeed(bounciness, speed)); } public void clear(){ View view = getTargetView(); if (view != null){ ViewParent viewParent = view.getParent(); if (viewParent instanceof ViewGroup){ ViewGroup parent = (ViewGroup) viewParent; parent.removeView(view); mTargetViewWeakReference.clear(); } } } }使用WeakReference来持有目标视图是一个很好的设计选择,它避免了内存泄漏问题,同时允许在需要时自动清理资源。
动画执行流程详解
了解了各个组件的实现后,让我们看看完整的动画执行流程:
第一步:构建动画参数
用户通过FloatingBuilder链式调用设置锚点视图、目标视图、偏移量和动画效果。
第二步:创建Floating容器
通过new Floating(activity)创建动画容器,内部会创建FloatingDecorView并添加到Activity的根布局中。
第三步:计算视图位置
Floating容器计算目标视图相对于锚点视图的精确位置,考虑到了全局坐标转换和视图尺寸差异。
第四步:添加视图到悬浮层
将目标视图添加到FloatingDecorView中,使用计算出的位置参数。
第五步:执行动画
调用具体的FloatingTransition实现,通过YumFloating包装器将动画属性应用到目标视图。
第六步:资源清理
动画结束后,YumFloating的clear()方法会从父视图中移除目标视图,释放相关资源。
设计亮点与最佳实践
1. 灵活的扩展机制
FloatingView的动画系统设计得非常灵活。开发者可以:
- 实现FloatingTransition接口创建自定义动画
- 继承BaseFloatingPathTransition实现复杂的路径动画
- 通过SpringHelper或直接使用Rebound物理引擎创建物理动画
2. 内存管理优化
- 使用WeakReference避免内存泄漏
- 提供clear()方法手动清理资源
- 自动从父视图移除动画视图
3. 坐标计算的精确性
通过getGlobalVisibleRect()和getLocationOnScreen()的组合使用,确保在不同屏幕尺寸和滚动位置下都能准确定位。
4. 物理动画支持
集成Facebook Rebound物理引擎,提供自然的弹簧动画效果,增强了用户体验。
实际应用示例
让我们通过一个简单的示例来看看如何使用FloatingView:
// 创建漂浮动画元素 FloatingElement element = new FloatingBuilder() .anchorView(anchorView) // 锚点视图 .targetView(targetView) // 目标视图 .offsetX(20) // X轴偏移 .offsetY(-30) // Y轴偏移 .floatingTransition(new ScaleFloatingTransition()) // 动画效果 .build(); // 创建漂浮容器并执行动画 Floating floating = new Floating(activity); floating.startFloating(element);性能优化建议
- 视图复用:对于频繁使用的漂浮动画,考虑复用目标视图
- 动画时长控制:根据场景调整动画时长,避免过长影响用户体验
- 资源及时释放:在不需要时调用YumFloating.clear()释放资源
- 避免过度绘制:确保目标视图不会过度复杂,影响动画性能
总结
FloatingView通过精心的架构设计,将复杂的漂浮动画实现封装成了简单易用的API。从FloatingBuilder的建造者模式,到Floating的容器管理,再到各种Transition的动画实现,每一层都体现了良好的设计原则。
这个库的成功之处在于:
- 简洁的API设计:链式调用让代码更加直观
- 灵活的扩展机制:支持自定义动画效果
- 优秀的性能表现:合理的资源管理和坐标计算
- 良好的兼容性:支持Android 3.0及以上版本
无论你是想要实现点赞动画、分享动画还是其他需要视觉反馈的场景,FloatingView都是一个值得考虑的解决方案。通过本文的源码解析,相信你已经对FloatingView的内部机制有了深入的理解,可以更好地在自己的项目中应用这个强大的动画库了!🚀
希望这篇源码解析能帮助你更好地理解和使用FloatingView。如果你有更多关于Android动画实现的问题,欢迎继续探索FloatingView的源码,相信你会发现更多有趣的设计细节!
【免费下载链接】FloatingViewFloatingView can make the target view floating above the anchor view with cool animation项目地址: https://gitcode.com/gh_mirrors/fl/FloatingView
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考