Android 12 SplashScreen API 以及Jetpack兼容库 您所在的位置:网站首页 app闪屏页作用 Android 12 SplashScreen API 以及Jetpack兼容库

Android 12 SplashScreen API 以及Jetpack兼容库

2024-01-10 03:32| 来源: 网络整理| 查看: 265

前言

1、什么是Android的冷启动时间?

冷启动时间是指点击桌面LOGO那一刻起到启动页面的Activity调用onCreate()之前的时间段。

2、冷启动的时间段内发生了什么?

在一个Activity打开时,如果Application还没有启动,系统会创建一个进程,进程的创建和初始化会消耗一些时间,在这个时间中,WindowManager会先加载APP的主题样式里的窗口背景(windowBackground)作为预览元素,然后才会真正的加载布局,如果这个时间过长,会给用户造成一种错觉:APP卡顿不流畅

常见做法 将背景设置为APP Logo,市面上大部分APP都是这么做的 @drawable/window_splash_screen_content 将背景设置为透明色,当点击桌面LOGO时并不会立即启动APP,而是在桌面停留一会(其实已经启动) @android:color/transparent

上面做法可以达到秒开效果,但属于掩耳盗铃。

Android 8.0

Google以前不推荐使用闪屏的使用,但是后来很多APP都在使用闪屏,Google希望让启动屏的制作更简单。

Android Oreo中提供了Splash Screen API,允许开发者把一个drawable资源设置为闪屏。

新建values-v26目录:

@drawable/window_splash_screen_content

通过windowSplashscreenContent设置的drawable资源将会覆盖在windowBackground顶部,在系统状态栏之下,如果不想受到System Bars限制,请使用全屏主题。

如未设置windowSplashscreenContent,系统仍会使用其他属性来展示闪屏页,如:windowBackground。

缺点

无法定义动画 无法控制时长 windowBackground设置时机

以为例

PhoneWindowManager

public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) { ... try { ... final PhoneWindow win = new PhoneWindow(context); win.setIsStartingWindow(true); win.setType(WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); ... final WindowManager.LayoutParams params = win.getAttributes(); ... addSplashscreenContent(win, context); wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); view = win.getDecorView(); wm.addView(view, params); // Only return the view if it was successfully added to the // window manager... which we can tell by it having a parent. return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null; } ... return null; } private void addSplashscreenContent(PhoneWindow win, Context ctx) { final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window); final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0); a.recycle(); if (resId == 0) { return; } final Drawable drawable = ctx.getDrawable(resId); if (drawable == null) { return; } // We wrap this into a view so the system insets get applied to the drawable. final View v = new View(ctx); v.setBackground(drawable); win.setContentView(v); } Android 12

Android12 增加了全新的SplashScreen API,可以为所有应用启用新的启动画面,包括启动时的应用运动、显示应用图标的启动画面,以及向应用本身的过渡。

工作原理

当用户启动应用,且应用进程未在运行(冷启动)或Activity尚未创建(温启动)时:

系统使用主题和自定义的动画来显示启动画面 当应用准备就绪时,会关闭启动画面并显示应用

热启动不会显示启动画面。

动画元素和机制

由窗口背景、动画形式的应用图标和图标背景组成:

应用图标(1)应该是矢量可绘制对象,也可以是静态或动画,动画图标会在启动画面显示时自动播放,时长不受限制,但建议不要超过1000毫秒,默认使用Launcher图标 图标背景(2)是可选的,在图标与窗口背景之间需要更高的对比度时很有用 窗口背景(4)由不透明的单色组成

启动画面动画由进入动画和退出动画组成:

进入动画由系统控制,不可自自定义 退出动画可自定义,可访问SplashScreenView以及ICON,可以设置任意动画(位移、透明度、颜色等),需要在动画执行完毕时手动移除启动画面 自定义启动画面

新建values-v31目录

#F18C1A @mipmap/ic_loading_logo 1000 #ffffff @drawable/window_splash_screen_content 让启动画面在屏幕上显示更长时间

当应用绘制第一帧后,启动画面会立即关闭。如果需要异步加载少量数据,可以使用ViewTreeObserver.OnPreDrawListener让应用暂停绘制第一帧。

companion object { const val DURATION = 2000 } private val initTime = SystemClock.uptimeMillis() val content: View = findViewById(android.R.id.content) content.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { override fun onPreDraw(): Boolean { return if ((SystemClock.uptimeMillis() - initTime) > DURATION) { content.viewTreeObserver.removeOnPreDrawListener(this) true } else false } }) 自定义退出动画

可以通过getSplashScreen() 来自定义退出动画

splashScreen.setOnExitAnimationListener { splashScreenView -> ... }

向中心缩小退出

@RequiresApi(Build.VERSION_CODES.S) private fun scaleExit(view: SplashScreenView) { ObjectAnimator.ofFloat(view, View.SCALE_X, View.SCALE_Y, Path().apply { moveTo(1f, 1f) lineTo(0f, 0f) }).apply { doOnEnd { view.remove() } start() } }

QQ录屏20210812092947.gif

ICON上滑退出

@RequiresApi(Build.VERSION_CODES.S) private fun slideUp(view: SplashScreenView) { val iconView = view.iconView ?: return AnimatorSet().apply { playSequentially( ObjectAnimator.ofFloat(iconView, View.TRANSLATION_Y, 0f, 50f), ObjectAnimator.ofFloat(iconView, View.TRANSLATION_Y, 50f, -view.height.toFloat()), ) doOnEnd { view.remove() } start() } }

QQ录屏20210812092807.gif

Jetpack SplashScreen

Jetpack发布了androidx.core:core-splashscreen:1.0.0-alpha01 以向后兼容新的 Splash Screen API,此Alpha版本包含向后移植到API 23的所有新API,图标背景除外,全球的Android设备中6及以上的版本占用率达到了9成以上。

如需了解更多信息,请参阅 androidx.core.splashscreen。

关键API说明SplashScreenJetpack版获取定制启动画面入口的类installSplashScreen()获取定制入口的静态成员函数setKeepVisibleCondition指定保持启动画面展示的条件KeepOnScreenCondition实现展示条件的接口setOnExitAnimationListener监听启动画面的退出时机OnExitAnimationListener启动画面退出的回调接口SplashScreenViewProvider定制退场效果的启动画面视图 Attr对比JetpackAndroid 12指定目标Activity主题postSplashScreenTheme-指定动画ICONwindowSplashScreenAnimatedIconandroid:windowSplashScreenAnimatedIcon指定启动画面背景windowSplashScreenBackgroundandroid:windowSplashScreenBackground指定Icon动画时长windowSplashScreenAnimationDurationandroid:windowSplashScreenAnimationDuration指定Icon背景-android:windowSplashScreenIconBackgroundColor指定品牌Logo-android:windowSplashScreenBrandingImage API对比JetpackAndroid 12启动画面定制入口class androidx.core.splashscreen.SplashScreeninterface android.window.SplashScreen入口实例获取Activity#installSplashScreen()Activity#getSplashScreen()启动画面视图SplashScreenViewProviderSplashScreenView

退场部分,无论是否运行在12,Jetpack SplashScreen都能达到Android 12同等效果,但进场部分在低版本存在一些局限:

暂时不支持ICON动画:AnimatedVectorDrawable 暂时不支持ICON背影:IconBackgroundColor 暂时不支持品牌LOGO:BrandingImage

面向低版本的进场效果本质是一个LayerDrawable,无法支持Vector Drawable动画、Adaptive Icon背景。

导入依赖 implementation 'androidx.core:core-splashscreen:1.0.0-alpha01' 基础主题配置 @mipmap/ic_loading_logo 1000 #f18c1a @style/UiTheme @color/purple_500 @color/purple_700 @color/white @color/teal_200 @color/teal_700 @color/black ?attr/colorPrimaryVariant Android 12主题配置 @mipmap/ic_launcher_round #ffffff @drawable/window_splash_screen_content Manifest配置 初始化

通过installSplashScreen() 获取SplashScreen实例,installSplashScreen() 必须先用setContentView调用,原因是install函数会获取postSplashScreenTheme 配置的主题,并在检查通过后setTheme 给Activity。

private lateinit var compatSplashScreen: SplashScreen override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) compatSplashScreen = installSplashScreen() setContentView(R.layout.activity_main) } 让启动画面在屏幕上显示更长时间 companion object { const val DURATION = 2000 } private val initTime = SystemClock.uptimeMillis() private fun compatDelay() { compatSplashScreen.setKeepVisibleCondition { (SystemClock.uptimeMillis() - initTime) < DURATION } } 自定义退出动画 compatSplashScreen.setOnExitAnimationListener { provider -> val iconView = provider.iconView AnimatorSet().apply { playSequentially( ObjectAnimator.ofFloat(iconView, View.TRANSLATION_Y, 0f, 50f), ObjectAnimator.ofFloat( iconView, View.TRANSLATION_Y, 50f, -provider.view.height.toFloat() ), ) doOnEnd { provider.remove() } start() } } 启动画面对比 Android 6Android 12


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有