FW Activity跳转动画源码解析(一)

文章目录

    • 跳转动画实际操作的是什么?
    • 窗口怎么知道应该执行什么动画,是透明,还是平移,还是缩放,旋转?

跳转动画实际操作的是什么?

startActivity调用之后进行页面跳转,会有一系列的涉及到ActivitStar,ActivityTask,ActivityManager等类的操作,最终在执行动画会调用到SurfaceControl中去,相关代码如下

public final class SurfaceControl implements Parcelable {
//省略代码@NonNullpublic Transaction setAlpha(@NonNull SurfaceControl sc,@FloatRange(from = 0.0, to = 1.0) float alpha) {checkPreconditions(sc);nativeSetAlpha(mNativeObject, sc.mNativeObject, alpha);return this;}
//省略代码@UnsupportedAppUsagepublic Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {matrix.getValues(float9);setMatrix(sc, float9[MSCALE_X], float9[MSKEW_Y],float9[MSKEW_X], float9[MSCALE_Y]);setPosition(sc, float9[MTRANS_X], float9[MTRANS_Y]);return this;}
//这个是调用到native的函数        @UnsupportedAppUsagepublic Transaction setMatrix(SurfaceControl sc,float dsdx, float dtdx, float dtdy, float dsdy) {checkPreconditions(sc);nativeSetMatrix(mNativeObject, sc.mNativeObject,dsdx, dtdx, dtdy, dsdy);return this;}@UnsupportedAppUsagepublic Transaction setPosition(SurfaceControl sc, float x, float y) {checkPreconditions(sc);nativeSetPosition(mNativeObject, sc.mNativeObject, x, y);return this;}
//省略代码
}

以上函数就负责了窗口的透明度以及大小,还有位置的变换.
可以看到相应的设置函数,最终都会调用到native层去,我们选一个cpp的代码看一下

//android_view_SurfaceControl.cpp
static void nativeSetPosition(JNIEnv* env, jclass clazz, jlong transactionObj,jlong nativeObject, jfloat x, jfloat y) {auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);transaction->setPosition(ctrl, x, y);
}//SurfaceComposerClient.cpp
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setPosition(const sp<SurfaceControl>& sc, float x, float y) {layer_state_t* s = getLayerState(sc);if (!s) {mStatus = BAD_INDEX;return *this;}s->what |= layer_state_t::ePositionChanged;s->x = x;s->y = y;registerSurfaceControlForCallback(sc);return *this;
}

以上代码调用到native去了之后会把相关设置的值赋值给layer,如果需要再cpp中定制动画相关的设置
可以修改这一块.

关于SurfaceControl 的调用链路如下图,WindowContainer,ActivityRecord大家应该都不陌生
在这里插入图片描述

窗口怎么知道应该执行什么动画,是透明,还是平移,还是缩放,旋转?

class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,BLASTSyncEngine.TransactionReadyListener {private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,boolean isVoiceInteraction) {//省略代码//通过Transition获取动画对象final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);//省略代码}                   
}public class AppTransition implements Dump {Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode,int orientation, Rect frame, Rect displayFrame, Rect insets,@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,boolean freeform, WindowContainer container) {//这里面有一堆判定,但是普通应用的时候是不会通过的,会再调用到loadAnimationAttra = animAttr != 0 ? loadAnimationAttr(lp, animAttr, transit) : null;return a;}//调用getCachedAnimations获取EntryAnimation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {int resId = Resources.ID_NULL;Context context = mContext;if (animAttr >= 0) {AttributeCache.Entry ent = getCachedAnimations(lp);if (ent != null) {context = ent.context;resId = ent.array.getResourceId(animAttr, 0);}}resId = updateToTranslucentAnimIfNeeded(resId, transit);if (ResourceId.isValid(resId)) {return loadAnimationSafely(context, resId);}return null;}//获取Styleable中的动画主题private AttributeCache.Entry getCachedAnimations(LayoutParams lp) {if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: layout params pkg="+ (lp != null ? lp.packageName : null)+ " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));if (lp != null && lp.windowAnimations != 0) {// If this is a system resource, don't try to load it from the// application resources.  It is nice to avoid loading application// resources if we can.String packageName = lp.packageName != null ? lp.packageName : "android";int resId = getAnimationStyleResId(lp);if ((resId&0xFF000000) == 0x01000000) {packageName = "android";}if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="+ packageName);return AttributeCache.instance().get(packageName, resId,com.android.internal.R.styleable.WindowAnimation, mCurrentUserId);}return null;}
}

在执行以上代码以后,就会从主题中获取到定义的窗口切换动画资源了.
相关的调用栈如下:
在这里插入图片描述

  • 获取到默认的启动动画资源,这个会对应一个anim的xml文件,以下文件位于frameworks/base/core/res/res/anim路径.
    android:anim/activity_open_enter

  • 退出的时候默认动画如下
    android:anim/activity_close_enter

在获取到以上资源以后动画会调用到WindowAnimationSpec类中去执行如下代码

@Overridepublic void apply(Transaction t, SurfaceControl leash, long currentPlayTime) {final TmpValues tmp = mThreadLocalTmps.get();tmp.transformation.clear();mAnimation.getTransformation(currentPlayTime, tmp.transformation);tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y);t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats);t.setAlpha(leash, tmp.transformation.getAlpha());boolean cropSet = false;if (mStackClipMode == STACK_CLIP_NONE) {if (tmp.transformation.hasClipRect()) {t.setWindowCrop(leash, tmp.transformation.getClipRect());cropSet = true;}} else {mTmpRect.set(mStackBounds);if (tmp.transformation.hasClipRect()) {mTmpRect.intersect(tmp.transformation.getClipRect());}t.setWindowCrop(leash, mTmpRect);cropSet = true;}// We can only apply rounded corner if a crop is set, as otherwise the value is meaningless,// since it doesn't have anything it's relative to.if (cropSet && mAnimation.hasRoundedCorners() && mWindowCornerRadius > 0) {t.setCornerRadius(leash, mWindowCornerRadius);}}

以上代码中 mAnimation.getTransformation(currentPlayTime, tmp.transformation);这一行就是通过之前得到的动画对象去计算应该设置的透明,平移等参数值,以用于去设置视图.
简单看一下这个计算吧,感兴趣的可以深入研究一下

public abstract class Animation implements Cloneable {public boolean getTransformation(long currentTime, Transformation outTransformation) {if (mStartTime == -1) {mStartTime = currentTime;}final long startOffset = getStartOffset();final long duration = mDuration;float normalizedTime;if (duration != 0) {normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /(float) duration;} else {// time is a step-change with a zero durationnormalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;}final boolean expired = normalizedTime >= 1.0f || isCanceled();mMore = !expired;if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {if (!mStarted) {fireAnimationStart();mStarted = true;if (NoImagePreloadHolder.USE_CLOSEGUARD) {guard.open("cancel or detach or getTransformation");}}if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);if (mCycleFlip) {normalizedTime = 1.0f - normalizedTime;}final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);applyTransformation(interpolatedTime, outTransformation);}if (expired) {if (mRepeatCount == mRepeated || isCanceled()) {if (!mEnded) {mEnded = true;guard.close();fireAnimationEnd();}} else {if (mRepeatCount > 0) {mRepeated++;}if (mRepeatMode == REVERSE) {mCycleFlip = !mCycleFlip;}mStartTime = -1;mMore = true;fireAnimationRepeat();}}if (!mMore && mOneMoreTime) {mOneMoreTime = false;return true;}return mMore;}}

以上在各种计算之后再调用到子类的applyTransformation函数去赋值给传入进来的对象Transformation outTransformation,赋值完了之后,后续的动画都会依赖这个计算出来的值进行设置了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/33092.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将一维机械振动信号构造为训练集和测试集(Python)

从如下链接中下载轴承数据集。 https://www.sciencedirect.com/science/article/pii/S2352340918314124 import numpy as np import scipy.io as sio import matplotlib.pyplot as plt import statistics as stats import pandas as pd from sklearn.model_selection import t…

在Ubuntu下将pulseaudio换成pipewire

1、为什么要将pulseaudio换成pipewire&#xff1f; PulseAudio 是一个成熟且广泛使用的音频服务器&#xff0c;适合一般桌面音频需求&#xff0c;但在性能和延迟上有一定限制。PipeWire 是一个更现代的解决方案&#xff0c;旨在统一音频和视频处理&#xff0c;提供高性能和低延…

微服务、多租户、单点登录、国产化形成的开源Java框架!

一、项目简介 JVS是软开企服构建的一站式数字化的开源框架&#xff0c;支持对接多种账户体系&#xff0c;支持多租户、支持Auth2、统一登录、单点登录等&#xff0c;支持原生开发、低代码/零代码开发应用。 二、框架核心功能 控制台(首页)&#xff1a;采用配置化的方式 用户…

已经被驳回的商标名称还可以申请不!

看到有网友在问&#xff0c;已经驳回的商标名称还可以申请不&#xff0c;普推商标知产老杨觉得要分析看情况&#xff0c;可以适当分析下看可不可以能申请&#xff0c;当然最终还是为了下证 &#xff0c;下证概率低的不建议申请。 先看驳回理由&#xff0c;如果商标驳回是绝对理…

华为某员工爆料:偷偷跑出去面试,被面试官鄙视了。第一句话就问:华为淘汰的吧,35岁了,这个年龄在华为能混得下去吗?身体没啥毛病吧

“你都35岁了&#xff0c;难不成是被华为淘汰的&#xff1f;在华为混不下去了吧&#xff1f;身体没啥毛病吧&#xff0c;我们这体检可是很严的。” 近日&#xff0c;一位华为员工在朋友圈爆料&#xff0c;自己在面试时遭到了面试官的无理取闹和人身攻击&#xff0c;原因仅仅是因…

【Java】内部类

认识内部类&#xff1a;Java中内部类分如下三种 匿名内部类 实例内部类 静态实例内部类 匿名内部类 匿名内部类顾名思义就是在创建的时候不用赋予名字。 代码演示&#xff1a; //匿名内部类 interface IA{void test(); } public class Main{public static void main(Str…

做国际期货有什么心得?

做过现货&#xff0c;外汇&#xff0c;国际期货&#xff0c;当然&#xff0c;做国际期货的时间比较多&#xff0c;几乎占用了我的交易生涯全部。现在&#xff0c;来讲讲我做国际期货的真实经历&#xff0c;交易历程和心得体会&#xff0c;希望正在做国际期货&#xff0c;或打算…

Sapphire开发日志 (十) 关于页面

关于页面 任务介绍 关于页面用户对我组工作量的展示。 实现效果 代码解释 首先封装一个子组件用于展示用户头像和名称。 const UserGrid ({src,name,size,link, }: {src: any;name: any;size?: any;link?: any; }) > (<Box sx{{ display: "flex", flex…

每日一练:攻防世界:5-1 MulTzor

一、XorTool 基于 XOR&#xff08;异或&#xff09;运算实现。它可以帮助您快速地对文本、二进制文件进行加密解密操作。 认识XorTool工具&#xff1a; 让我们先去认识一下工具&#xff1a; xortool.py 是基于 python 的脚本&#xff0c;用于完成一些 xor 分析&#xff0c;…

【云计算 复习】第6节 AWS亚马逊

一、基础存储架构Dynamo 1.概述 &#xff08;1&#xff09;为了保证其稳定性&#xff0c;Amazon的系统采用完全的分布式、去中心化的架构。 &#xff08;2&#xff09;Dynamo只支持简单的键值对方式的数据存储&#xff0c;不支持复杂的查询 &#xff08;3&#xff09;Dynamo中…

腾讯 MOFA-Video: 可控制图转视频

腾讯 MOFA-Video: 可控制图转视频 MOFA-Video 它支持运动轨迹、人脸关键点并支持将其混合控制图像转换为视频。 混合控制: 结合图像、控制信号和关键点生成动画。 运动画笔: 结合图像、轨迹和画笔生成动画。 控制比例: 调整动画的控制比例&#xff0c;从纯 SVD 到完全控制。 通…

“人工智能+”带来新变化

以生成式人工智能&#xff08;AIGC&#xff09;为代表的新一代人工智能技术创新加速演进&#xff0c;相关商业化应用成果也不断涌现&#xff0c;行业应用范围不断拓展&#xff0c;深度赋能实体经济&#xff0c;为行业提质增效与实现减排提供助力。 自主航运初创公司OrcaAI于6月…

Appium+python自动化(二十一)- 让猴子按你指令大闹手机,让我们都成为耍猴高手(超详解)

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 简介  一年一度的暑假如期而至&#xff0c;每年必不可少的&#xff0c;便是《西游记》这部经典电视连续剧的播出&#xff0c;作为一名90后&#xff0c;对于这部经典剧的情谊&#xff…

深度学习工具jupyter创建并检测pytorch环境以及安装工具包

1. 前言 确保已经安装Python和anaconda&#xff08;anaconda一般自带jupyter&#xff09;。然后创建一个jupyter环境&#xff0c;查看启动后的new有没有环境选项。 如果遇到了EnvironmentLocationNotFound:Not such a environment。说明conda环境安装位置有问题&#xff0c;往…

Raspberry Pi AI Kit——Hailo-8L安装记录(预告)

Hailo-8的测试见往期文章&#xff0c;最近树莓派发布了官方套件——Raspberry Pi AI Kit&#xff0c;其采用Hailo-8L&#xff0c;算力为13TOPS&#xff0c;是Hailo-8算力的一半&#xff0c;官网地址为 Raspberry Pi AI Kit安装 最近在进行Raspberry Pi AI Kit使用测试 !](htt…

建议收藏!100款宝藏级AIGC工具分享,70款ChatGPT插件惊艳的开发过程与宏大的商业化愿景

建议收藏&#xff01;100款宝藏级AIGC工具分享&#xff0c;70款ChatGPT插件惊艳的开发过程与宏大的商业化愿景。 不输ChatGPT&#xff1f;整理了100款AIGC神器&#xff0c;打工人速进。 说到AIGC工具&#xff0c;你还是只知道ChatGPT&#xff1f; 实际上&#xff0c;越来越多…

景联文科技实力入选「2024中国AI大模型产业图谱1.0版」!

近日&#xff0c;数据智能产业创新服务媒体数据猿联合上海大数据联盟共同发布《2024中国AI大模型产业图谱1.0版》&#xff0c;从大数据和人工智能等智能技术的核心出发&#xff0c;全面覆盖整个产业链&#xff0c;为行业提供更为精细且直观的专业导向。 景联文科技凭借高质量数…

小区业主管理系统

摘 要 随着城市化进程的加速和人口的不断增加&#xff0c;小区的数量也在不断增加。小区作为城市居民居住的主要场所&#xff0c;其管理工作也变得越来越重要。传统的小区业主管理方式存在诸多问题&#xff0c;如信息传递不畅、业务处理效率低下等。因此&#xff0c;开发一个高…

“明天下班以后请假了,孩子中考“

「作者简介」&#xff1a;冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础著作 《网络安全自学教程》&#xff0c;适合基础薄弱的同学系统化的学习网络安全&#xff0c;用最短的时间掌握最核心的技术。 前几天约服务器…

轻轻一按,即可加速您的 Mac

一键智能清理 让你的 Mac 电脑焕然一新 CleanMyMac X 是一款专业的 Mac 电脑清理软件&#xff0c;支持一键扫描 Mac 磁盘垃圾&#xff0c;智能清理垃圾文件和系统语言安装包&#xff0c;快速释放磁盘空间&#xff0c;让你的 Mac 电脑焕然一新&#xff01; 智能扫描一键清理 Ma…