FloatingView源码解析:从FloatingBuilder到动画执行的完整流程
2026/7/6 16:25:39 网站建设 项目流程

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)相结合的设计。整个架构分为三个主要层次:

  1. 配置层:FloatingBuilder负责构建动画参数
  2. 容器层:Floating负责管理动画视图和生命周期
  3. 动画层:各种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中实现,是整个动画系统的核心容器。它的主要职责包括:

  1. 创建和管理悬浮装饰视图:通过FloatingDecorView将目标视图添加到Activity的根布局中
  2. 坐标计算和定位:计算目标视图相对于锚点视图的位置
  3. 动画启动:调用具体的动画实现
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中定义,它起到了桥梁作用:

  1. 视图操作代理:将动画属性应用到实际的目标视图
  2. 物理引擎集成:封装了Facebook Rebound物理引擎的创建和使用
  3. 资源管理:提供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);

性能优化建议

  1. 视图复用:对于频繁使用的漂浮动画,考虑复用目标视图
  2. 动画时长控制:根据场景调整动画时长,避免过长影响用户体验
  3. 资源及时释放:在不需要时调用YumFloating.clear()释放资源
  4. 避免过度绘制:确保目标视图不会过度复杂,影响动画性能

总结

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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询