MaterialSheetFab源码深度剖析:揭秘FAB与Sheet过渡动画的底层逻辑

【免费下载链接】material-sheet-fab Android library that provides the floating action button to sheet transition from Google's Material Design. 【免费下载链接】material-sheet-fab 项目地址: https://gitcode.com/gh_mirrors/ma/material-sheet-fab

MaterialSheetFab是一个实现Material Design中FAB(浮动操作按钮)与底部表单平滑过渡动画的Android库。本文将从核心实现逻辑出发,解析其如何通过精心设计的动画系统实现流畅的视觉体验,帮助开发者理解Android自定义动画的关键技术点。

核心功能与视觉效果展示

MaterialSheetFab的核心价值在于实现了FAB与底部操作表单之间的无缝过渡。当用户点击FAB时,按钮会通过缩放、颜色渐变和路径动画转换为底部表单;关闭表单时则执行相反的动画过程,恢复为FAB状态。

FAB到Sheet的过渡效果 图1:FAB点击后展开为底部操作表单的动画效果

Sheet折叠回FAB的过程 图2:底部表单折叠恢复为FAB的状态

这种过渡动画遵循Material Design的"形态转换"原则,通过视觉连贯性增强用户对操作流程的理解。

核心类结构与动画系统设计

MaterialSheetFab类:协调控制中心

核心控制类MaterialSheetFab位于material-sheet-fab/src/main/java/com/gordonwong/materialsheetfab/MaterialSheetFab.java,采用泛型设计支持不同类型的FAB实现:

public class MaterialSheetFab<FAB extends View & AnimatedFab> {
    private static final boolean IS_LOLLIPOP = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
    
    // 动画控制器
    protected FabAnimation fabAnimation;
    protected MaterialSheetAnimation sheetAnimation;
    protected OverlayAnimation overlayAnimation;
    
    // 状态管理
    protected int anchorX;
    protected int anchorY;
    private boolean isShowing;
    private boolean isHiding;
}

该类通过组合三个动画控制器实现完整的过渡效果:

  • FabAnimation:处理FAB自身的缩放和位移动画
  • MaterialSheetAnimation:管理表单的揭示动画和颜色过渡
  • OverlayAnimation:控制背景遮罩的淡入淡出效果

动画常量设计:兼顾兼容性与视觉体验

库中定义了精细的动画参数,针对不同Android版本优化体验:

// 动画时长(毫秒)
private static final int SHEET_ANIM_DURATION = (IS_LOLLIPOP ? 600 : 300) * ANIMATION_SPEED;
private static final int FAB_ANIM_DURATION = 300 * ANIMATION_SPEED;

// 动画延迟
private static final int SHOW_SHEET_ANIM_DELAY = (int) (FAB_ANIM_DURATION * 0.5);
private static final int MOVE_FAB_ANIM_DELAY = IS_LOLLIPOP ? (int) (SHEET_ANIM_DURATION * 0.3)
        : (int) (SHEET_ANIM_DURATION * 0.6);

通过条件判断为Android Lollipop及以上版本提供更流畅的动画(600ms),旧版本则使用更快的动画(300ms)确保响应速度。

关键动画实现原理

1. FAB到Sheet的转换过程

morphIntoSheet方法实现了FAB到表单的核心转换逻辑:

protected void morphIntoSheet(final AnimationListener endListener) {
    // 更新FAB锚点位置
    updateFabAnchor();
    
    // 对齐表单与FAB位置
    sheetAnimation.alignSheetWithFab(fab);
    
    // FAB变形动画
    fabAnimation.morphIntoSheet(
        sheetAnimation.getSheetRevealCenterX(),
        sheetAnimation.getSheetRevealCenterY(fab),
        getFabArcSide(sheetAnimation.getRevealXDirection()), 
        FAB_ARC_DEGREES,
        FAB_SCALE_FACTOR, 
        FAB_ANIM_DURATION, 
        null
    );
    
    // 延迟显示表单
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            fab.setVisibility(View.INVISIBLE);
            sheetAnimation.morphFromFab(fab, SHEET_ANIM_DURATION,
                    SHOW_SHEET_COLOR_ANIM_DURATION, endListener);
        }
    }, SHOW_SHEET_ANIM_DELAY);
}

整个过程分为三个阶段:

  1. 记录FAB当前位置作为动画起始点
  2. 执行FAB缩放和位移动画
  3. 延迟启动表单的圆形揭示动画

2. 圆形揭示动画实现

表单动画由MaterialSheetAnimation类处理,利用Android的ViewAnimationUtils.createCircularReveal API实现圆形扩展效果:

protected SupportAnimator createRevealAnimator(boolean isReveal, int centerX, int centerY,
        float startRadius, float endRadius) {
    SupportAnimator animator;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        if (isReveal) {
            animator = ViewAnimationUtils.createCircularReveal(sheet, centerX, centerY,
                    startRadius, endRadius);
        } else {
            animator = ViewAnimationUtils.createCircularReveal(sheet, centerX, centerY,
                    startRadius, endRadius);
        }
    } else {
        animator = io.codetail.animation.ViewAnimationUtils.createCircularReveal(sheet,
                centerX, centerY, startRadius, endRadius);
    }
    animator.setInterpolator(interpolator);
    animator.setDuration(duration);
    return animator;
}

通过封装不同Android版本的API调用,确保了动画效果的兼容性。

3. 颜色过渡动画

颜色动画使用ArgbEvaluator实现FAB颜色到表单颜色的平滑过渡:

private ValueAnimator createColorAnimator(int startColor, int endColor, long duration) {
    ValueAnimator colorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), startColor, endColor);
    colorAnim.setDuration(duration);
    colorAnim.setInterpolator(interpolator);
    colorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animator) {
            int color = (int) animator.getAnimatedValue();
            setBackgroundColor(color);
        }
    });
    return colorAnim;
}

实际应用与扩展

基础使用流程

  1. 在布局文件中定义FAB、表单和遮罩视图
  2. 创建MaterialSheetFab实例并配置参数
  3. 设置事件监听器处理表单显示/隐藏事件

自定义动画参数

通过修改以下关键参数可以调整动画效果:

  • ANIMATION_SPEED:整体动画速度系数
  • FAB_SCALE_FACTOR:FAB缩放比例
  • FAB_ARC_DEGREES:FAB移动轨迹的弧度
  • RevealXDirection/RevealYDirection:表单展开方向

性能优化建议

  1. 避免在动画期间执行复杂计算
  2. 对频繁触发的动画使用硬件加速
  3. 考虑为低端设备降低动画复杂度

总结与扩展学习

MaterialSheetFab通过精心设计的动画协调机制,实现了符合Material Design规范的高质量过渡效果。其核心价值在于:

  1. 分层动画设计:将复杂动画分解为独立模块,提高可维护性
  2. 版本兼容处理:通过封装适配不同Android版本的动画API
  3. 参数化控制:通过常量定义使动画效果可配置

对于希望深入学习Android动画的开发者,建议进一步研究:

  • io.codetail.animation包下的动画兼容实现
  • FabAnimation中的路径动画算法
  • MaterialSheetAnimation中的视图位置计算逻辑

通过掌握这些技术点,开发者可以构建更加流畅、自然的自定义动画效果,提升应用的整体用户体验。

【免费下载链接】material-sheet-fab Android library that provides the floating action button to sheet transition from Google's Material Design. 【免费下载链接】material-sheet-fab 项目地址: https://gitcode.com/gh_mirrors/ma/material-sheet-fab

Logo

立足具身智能前沿赛道,致力于搭建全球化、开源化、全栈式技术交流与实践共创平台。

更多推荐