当前位置: 首页 > ds >正文

Android 关闭Activity切换过渡动画

Android 9.0以前关闭过渡动画效果只需要把开发者模式中过渡动画缩放设为0就可以。也就是把def_window_transition_scale改为0%

frameworks/base/packages/SettingsProvider/res/values/defaults.xml+    <fraction name="def_window_transition_scale">100%</fraction>
-    <fraction name="def_window_transition_scale">0%</fraction>

9.0以后按这种方式修改后屏幕会闪一下黑屏,整个窗口会抖动一下,感觉动画没有完全关闭。

跟下流程发现还是有些不一样的地方。

    void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,boolean newTask, boolean keepCurTransition, ActivityOptions options) {TaskRecord rTask = r.getTask();final int taskId = rTask.taskId;// mLaunchTaskBehind tasks get placed at the back of the task stack.if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {// Last activity in task had been removed or ActivityManagerService is reusing task.// Insert or replace.// Might not even be in.insertTaskAtTop(rTask, r);}TaskRecord task = null;if (!newTask) {// If starting in an existing task, find where that is...boolean startIt = true;for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {task = mTaskHistory.get(taskNdx);if (task.getTopActivity() == null) {// All activities in task are finishing.continue;}if (task == rTask) {// Here it is!  Now, if this is not yet visible to the// user, then just add it without starting; it will// get started when the user navigates back to it.if (!startIt) {if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "+ task, new RuntimeException("here").fillInStackTrace());r.createWindowContainer();ActivityOptions.abort(options);return;}break;} else if (task.numFullscreen > 0) {startIt = false;}}}// Place a new activity at top of stack, so it is next to interact with the user.// If we are not placing the new activity frontmost, we do not want to deliver the// onUserLeaving callback to the actual frontmost activityfinal TaskRecord activityTask = r.getTask();if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {mStackSupervisor.mUserLeaving = false;if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,"startActivity() behind front, mUserLeaving=false");}task = activityTask;// Slot the activity into the history stack and proceedif (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,new RuntimeException("here").fillInStackTrace());// TODO: Need to investigate if it is okay for the controller to already be created by the// time we get to this point. I think it is, but need to double check.// Use test in b/34179495 to trace the call path.if (r.getWindowContainerController() == null) {r.createWindowContainer();}task.setFrontOfTask();if (!isHomeOrRecentsStack() || numActivities() > 0) {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,"Prepare open transition: starting " + r);//app设置FLAG_ACTIVITY_NO_ANIMATION,主动禁用过渡动画if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {mWindowManager.prepareAppTransition(TRANSIT_NONE, keepCurTransition);mStackSupervisor.mNoAnimActivities.add(r);} else {int transit = TRANSIT_ACTIVITY_OPEN;if (newTask) {if (r.mLaunchTaskBehind) {transit = TRANSIT_TASK_OPEN_BEHIND;} else {// If a new task is being launched, then mark the existing top activity as// supporting picture-in-picture while pausing only if the starting activity// would not be considered an overlay on top of the current activity// (eg. not fullscreen, or the assistant)if (canEnterPipOnTaskSwitch(focusedTopActivity,null /* toFrontTask */, r, options)) {focusedTopActivity.supportsEnterPipOnTaskSwitch = true;}transit = TRANSIT_TASK_OPEN;}}//准备过渡动画mWindowManager.prepareAppTransition(transit, keepCurTransition);mStackSupervisor.mNoAnimActivities.remove(r);}boolean doShow = true;if (newTask) {// Even though this activity is starting fresh, we still need// to reset it to make sure we apply affinities to move any// existing activities from other tasks in to it.// If the caller has requested that the target task be// reset, then do so.if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {resetTaskIfNeededLocked(r, r);doShow = topRunningNonDelayedActivityLocked(null) == r;}} else if (options != null && options.getAnimationType()== ActivityOptions.ANIM_SCENE_TRANSITION) {doShow = false;}if (r.mLaunchTaskBehind) {// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we// tell WindowManager that r is visible even though it is at the back of the stack.r.setVisibility(true);ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);} else if (SHOW_APP_STARTING_PREVIEW && doShow) {// Figure out if we are transitioning from another activity that is// "has the same starting icon" as the next one.  This allows the// window manager to keep the previous window it had previously// created, if it still had one.TaskRecord prevTask = r.getTask();ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();if (prev != null) {// We don't want to reuse the previous starting preview if:// (1) The current activity is in a different task.if (prev.getTask() != prevTask) {prev = null;}// (2) The current activity is already displayed.else if (prev.nowVisible) {prev = null;}}r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));}} else {// If this is the first activity, don't do any fancy animations,// because there is nothing for it to animate on top of.ActivityOptions.abort(options);}}

最终通过调用next.setVisibility(true),调用到AppWindowToken中的setVisibility方法中把要切换的activity设为可见状态。

boolean setVisibility(WindowManager.LayoutParams lp,boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {boolean delayed = false;inPendingTransaction = false;// Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually// been set by the app now.mHiddenSetFromTransferredStartingWindow = false;// Allow for state changes and animation to be applied if:// * token is transitioning visibility state// * or the token was marked as hidden and is exiting before we had a chance to play the// transition animation// * or this is an opening app and windows are being replaced.boolean visibilityChanged = false;if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {final AccessibilityController accessibilityController = mService.mAccessibilityController;boolean changed = false;if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,"Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);boolean runningAppAnimation = false;if (transit != WindowManager.TRANSIT_UNSET) {//使用动画,9.0之前该方法实现是在WindowManagerService中if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {delayed = runningAppAnimation = true;}final WindowState window = findMainWindow();//TODO (multidisplay): Magnification is supported only for the default display.if (window != null && accessibilityController != null&& getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {accessibilityController.onAppWindowTransitionLocked(window, transit);}changed = true;}...

看下applyAnimationLocked,有这样一段代码

boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,boolean isVoiceInteraction) {//判断是否已禁用TransationAnimationif (mService.mDisableTransitionAnimation || !shouldAnimate(transit)) {if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."+ " atoken=" + this);}cancelAnimation();return false;}// Only apply an animation if the display isn't frozen. If it is frozen, there is no reason...

接着看WindowManagerService

WindowManagerService(Context context, InputManagerService inputManager,boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,WindowManagerPolicy policy) {installLock(this, INDEX_WINDOW);mContext = context;mHaveInputMethods = haveInputMethods;mAllowBootMessages = showBootMsgs;mOnlyCore = onlyCore;mLimitedAlphaCompositing = context.getResources().getBoolean(com.android.internal.R.bool.config_sf_limitedAlpha);mHasPermanentDpad = context.getResources().getBoolean(com.android.internal.R.bool.config_hasPermanentDpad);mInTouchMode = context.getResources().getBoolean(com.android.internal.R.bool.config_defaultInTouchMode);mDrawLockTimeoutMillis = context.getResources().getInteger(com.android.internal.R.integer.config_drawLockTimeoutMillis);mAllowAnimationsInLowPowerMode = context.getResources().getBoolean(com.android.internal.R.bool.config_allowAnimationsInLowPowerMode);mMaxUiWidth = context.getResources().getInteger(com.android.internal.R.integer.config_maxUiWidth);//直接读取configmDisableTransitionAnimation = context.getResources().getBoolean(com.android.internal.R.bool.config_disableTransitionAnimation);mInputManager = inputManager; // Must be before createDisplayContentLocked.mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);mDisplaySettings = new DisplaySettings();mDisplaySettings.readSettingsLocked();

最后尝试把config_disableTransitionAnimation改为true,验证过渡动画关闭并且没有闪屏。

http://www.xdnf.cn/news/5308.html

相关文章:

  • 栈溢出攻击最基本原理
  • 宝塔服务安装使用的保姆级教程
  • Redis 集群
  • 安装或更新 CUDA Toolkit - Ubuntu - RuntimeError
  • CAD属性图框值与Excel联动(CAD块属性导出Excel、excel更新CAD块属性)——CAD c#二次开发
  • WPF中如何自定义控件
  • 【Oracle认证】MySQL 8.0 OCP 认证考试英文版(MySQL30 周年版)
  • #Redis黑马点评#(四)优惠券秒杀
  • Fabric系列 - SoftHSM 软件模拟HSM
  • 前端SSE技术详解:从入门到实战的完整指南
  • C++泛型编程(二):现代C++特性
  • 常见的降维算法
  • 采用SqlSugarClient创建数据库实例引发的异步调用问题
  • 【Qt/C++】深入理解 Lambda 表达式与 `mutable` 关键字的使用
  • MySQL的视图
  • AI 助力,轻松进行双语学术论文翻译!
  • C++GO语言微服务之gorm框架操作MySQL
  • uniapp使用ui.request 请求流式输出
  • LLaVA:开源多模态大语言模型深度解析
  • 物品识别 树莓派4 YOLO v11
  • 青少年编程与数学 02-019 Rust 编程基础 05课题、复合数据类型
  • 解锁 DevOps 新境界 :使用 Flux 进行 GitOps 现场演示 – 自动化您的 Kubernetes 部署
  • 大模型(LLMs)强化学习——RLHF及其变种
  • 基于强化学习 Q-learning 算法求解城市场景下无人机三维路径规划研究,提供完整MATLAB代码
  • linux测试硬盘读写速度
  • uniapp|实现商品分类与列表数据联动,左侧菜单右侧商品列表(瀑布流、高度自动计算、多端兼容)
  • 音频类网站或者资讯总结
  • 电子电器架构 --- 车载以太网拓扑
  • OSPF的四种特殊区域(Stub、Totally Stub、NSSA、Totally NSSA)详解
  • PyTorch 线性回归模型构建与神经网络基础要点解析