0

0

Fab 和 Dialog 之间的过渡效果(Fab and Dialog Morphing Animation)_html/css_WEB-ITnose

php中文网

php中文网

发布时间:2016-06-21 08:59:11

|

1511人浏览过

|

来源于php中文网

原创

最近在读Plaid的源码,发现fab和dialog之间切换的动画效果好舒服,于是就研究了下,将其从Plaid项目中抽离出来,然后再改进了些代码,更加方便易懂,也更加简单易用。效果如下,项目源码地址

实现原理分析

1.在前面的《Android群英传》的读书笔记中提到过Activity共享元素过渡动画的实现方式

共享元素过渡动画:一个共享元素过渡动画决定两个Activity之间的过渡怎么共享它们的视图,包括了
changeBounds:改变目标视图的布局边界;
changeClipBounds:裁剪目标视图的边界;
changeTransform:改变目标视图的缩放比例和旋转角度;
changeImageTransform:改变目标图片的大小和缩放比例。
使用方式:假设Activity从A跳转到B,那么将A中原来的startActivity改为如下代码:

立即学习前端免费学习笔记(深入)”;

//单个共享元素的调用方式startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this, view, "share").toBundle());//多个共享元素的调用方式startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this,                Pair.create(view, "share"),                Pair.create(fab, "fab")).toBundle());

然后在B的onCreate方法中添加如下代码:

//声明需要开启Activity过渡动画getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

其次还要在Activity A和B的布局文件中为共享元素组件添加android:transitionName="xxx"属性。

2.源码中的Dialog实际上是Activity,并设置了android:windowIsTranslucent为true,所以从fab到dialog的动画效果实际上是Activity的过渡动画。但是,如果单纯的只是使用Activity的共享元素过渡动画,将fab作为共享元素的话,效果并不好,不是那么的舒服。

ModelGate
ModelGate

一站式AI模型管理与调用工具

下载

3.为了让过渡效果更加舒服,这里添加了两个渐变效果,一个是color,从fab的颜色到dialog的背景颜色的渐变;另一个是cornerRadius,即圆角幅度的渐变。请看下面的代码实现:

/** * MorphTransition扩展自ChangeBounds(共享元素的动画的一种),它在原有动画基础上添加了color和cornerRadius的动画效果,这个类实际上是整合了MorphFabToDialog和MorphDialogToFab两个类的作用 * <p/> * A transition that morphs a circle into a rectangle, changing it's background color. */public class MorphTransition extends ChangeBounds {    private static final String PROPERTY_COLOR = "color";    private static final String PROPERTY_CORNER_RADIUS = "cornerRadius";    private static final String[] TRANSITION_PROPERTIES = {            PROPERTY_COLOR,            PROPERTY_CORNER_RADIUS    };    private int startColor = Color.TRANSPARENT;    private int endColor = Color.TRANSPARENT;    private int startCornerRadius = 0;    private int endCornerRadius = 0;    private boolean isShowViewGroup = false;    public MorphTransition(int startColor, int endColor, int startCornerRadius, int endCornerRadius, boolean isShowViewGroup) {        super();        setStartColor(startColor);        setEndColor(endColor);        setStartCornerRadius(startCornerRadius);        setEndCornerRadius(endCornerRadius);        setIsShowViewGroup(isShowViewGroup);    }    public MorphTransition(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public String[] getTransitionProperties() {        return TRANSITION_PROPERTIES;    }    @Override    public void captureStartValues(TransitionValues transitionValues) {        super.captureStartValues(transitionValues);        final View view = transitionValues.view;        if (view.getWidth() <= 0 || view.getHeight() <= 0) {            return;        }        transitionValues.values.put(PROPERTY_COLOR, startColor);        transitionValues.values.put(PROPERTY_CORNER_RADIUS, startCornerRadius);//view.getHeight() / 2    }    @Override    public void captureEndValues(TransitionValues transitionValues) {        super.captureEndValues(transitionValues);        final View view = transitionValues.view;        if (view.getWidth() <= 0 || view.getHeight() <= 0) {            return;        }        transitionValues.values.put(PROPERTY_COLOR, endColor);//ContextCompat.getColor(view.getContext(), R.color.dialog_background_color)        transitionValues.values.put(PROPERTY_CORNER_RADIUS, endCornerRadius);    }    @Override    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues, final TransitionValues endValues) {        Animator changeBounds = super.createAnimator(sceneRoot, startValues, endValues);        if (startValues == null || endValues == null || changeBounds == null) {            return null;        }        Integer startColor = (Integer) startValues.values.get(PROPERTY_COLOR);        Integer startCornerRadius = (Integer) startValues.values.get(PROPERTY_CORNER_RADIUS);        Integer endColor = (Integer) endValues.values.get(PROPERTY_COLOR);        Integer endCornerRadius = (Integer) endValues.values.get(PROPERTY_CORNER_RADIUS);        if (startColor == null || startCornerRadius == null || endColor == null || endCornerRadius == null) {            return null;        }        MorphDrawable background = new MorphDrawable(startColor, startCornerRadius);        endValues.view.setBackground(background);        Animator color = ObjectAnimator.ofArgb(background, background.COLOR, endColor);        Animator corners = ObjectAnimator.ofFloat(background, background.CORNER_RADIUS, endCornerRadius);        ////......        AnimatorSet transition = new AnimatorSet();        transition.playTogether(changeBounds, corners, color);        transition.setDuration(300);        transition.setInterpolator(AnimationUtils.loadInterpolator(sceneRoot.getContext(), android.R.interpolator.fast_out_slow_in));        return transition;    }    public void setEndColor(int endColor) {        this.endColor = endColor;    }    public void setEndCornerRadius(int endCornerRadius) {        this.endCornerRadius = endCornerRadius;    }    public void setStartColor(int startColor) {        this.startColor = startColor;    }    public void setStartCornerRadius(int startCornerRadius) {        this.startCornerRadius = startCornerRadius;    }    public void setIsShowViewGroup(boolean isShowViewGroup) {        this.isShowViewGroup = isShowViewGroup;    }}

4.上面的代码中用到了MorphDrawable类,它继承自Drawable,并添加了前面提到的那两个属性以用于产生属性动画,默认是没有为那两个属性添加set/get方法的,所以需要进行扩展。关于属性动画可以看以前的读书笔记,重要代码如下:

/** * 形态和颜色可以发生变化的Drawable,形态变化是通过cornerRadius来实现的,颜色变化是通过paint的color来实现的 * 该类在Drawable的基础上添加了cornerRadius和color两个属性,前者是float类型,后者是int类型 * <p/> * A drawable that can morph size, shape (via it's corner radius) and color.  Specifically this is * useful for animating between a FAB and a dialog. */public class MorphDrawable extends Drawable {    private Paint paint;    private float cornerRadius;    public static final Property<MorphDrawable, Float> CORNER_RADIUS = new Property<MorphDrawable, Float>(Float.class, "cornerRadius") {        @Override        public void set(MorphDrawable morphDrawable, Float value) {            morphDrawable.setCornerRadius(value);        }        @Override        public Float get(MorphDrawable morphDrawable) {            return morphDrawable.getCornerRadius();        }    };    public static final Property<MorphDrawable, Integer> COLOR = new Property<MorphDrawable, Integer>(Integer.class, "color") {        @Override        public void set(MorphDrawable morphDrawable, Integer value) {            morphDrawable.setColor(value);        }        @Override        public Integer get(MorphDrawable morphDrawable) {            return morphDrawable.getColor();        }    };    public MorphDrawable(@ColorInt int color, float cornerRadius) {        this.cornerRadius = cornerRadius;        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        paint.setColor(color);    }    public float getCornerRadius() {        return cornerRadius;    }    public void setCornerRadius(float cornerRadius) {        this.cornerRadius = cornerRadius;        invalidateSelf();    }    public int getColor() {        return paint.getColor();    }    public void setColor(int color) {        paint.setColor(color);        invalidateSelf();    }    @Override    public void draw(Canvas canvas) {        canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right, getBounds()                .bottom, cornerRadius, cornerRadius, paint);//hujiawei    }    @Override    public void getOutline(Outline outline) {        outline.setRoundRect(getBounds(), cornerRadius);    }    @Override    public void setAlpha(int alpha) {        paint.setAlpha(alpha);        invalidateSelf();    }    @Override    public void setColorFilter(ColorFilter cf) {        paint.setColorFilter(cf);        invalidateSelf();    }    @Override    public int getOpacity() {        return paint.getAlpha();    }}

5.有了前面的准备之后,就可以在dialog中配置进入和退出的动画效果了,重要代码如下:

//DialogActivity.javapublic void setupSharedEelementTransitions2() {    ArcMotion arcMotion = new ArcMotion();    arcMotion.setMinimumHorizontalAngle(50f);    arcMotion.setMinimumVerticalAngle(50f);    Interpolator easeInOut = AnimationUtils.loadInterpolator(this, android.R.interpolator.fast_out_slow_in);    //hujiawei 100是随意给的一个数字,可以修改,需要注意的是这里调用container.getHeight()结果为0    MorphTransition sharedEnter = new MorphTransition(ContextCompat.getColor(this, R.color.fab_background_color),            ContextCompat.getColor(this, R.color.dialog_background_color), 100, getResources().getDimensionPixelSize(R.dimen.dialog_corners), true);    sharedEnter.setPathMotion(arcMotion);    sharedEnter.setInterpolator(easeInOut);    MorphTransition sharedReturn = new MorphTransition(ContextCompat.getColor(this, R.color.dialog_background_color),            ContextCompat.getColor(this, R.color.fab_background_color), getResources().getDimensionPixelSize(R.dimen.dialog_corners), 100,  false);    sharedReturn.setPathMotion(arcMotion);    sharedReturn.setInterpolator(easeInOut);    if (container != null) {        sharedEnter.addTarget(container);        sharedReturn.addTarget(container);    }    getWindow().setSharedElementEnterTransition(sharedEnter);    getWindow().setSharedElementReturnTransition(sharedReturn);}

6.从上面的分析可以看出,这个方案比较容易扩展,只要是该类型的动画,使用开始和结束时的对应颜色和圆角值就可以构造相应的MorphTransition,将MorphTransition设置为Activity的进入或者退化动画即可。

以上是我的分析和理解,有任何问题欢迎大家指点 �(^ω^)�

原文:Fab and Dialog Morphing Animation 

来自: http://www.jcodecraeer.com//a/anzhuokaifa/2015/1215/3776.html

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

46

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

178

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

51

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

227

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

532

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

171

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号