如何炫酷的解决Activity启动黑白屏问题

先上图。注意看底部,点击图标时会直接显示icon,然后在加载SplashActivity的View。使用的机型是oneplus 5t ,系统是android9.0。
在这里插入图片描述
首先要说明的是无论是APP启动,还是startActivity都是Activity的启动,最后都是ActivityManagerService启动一个新的Activity。咱们先看一下闪屏的原因。

闪屏的原因

当点击桌面的launch图标(桌面的launch也是一个app应用)时,如果这个Activity所属Application还没有在运行,系统会为这个Activity的先Fork出一个新进程(在Dalvik虚拟机中,每一个Application都是一个进程),但进程的创建与初始化都需要时间,在这个动作完成之前,如果初始化的时间过长,屏幕上可能没有任何动静,用户会以为没有点到按钮。

所以既不能停在原来的地方又没到显示新的界面,怎么办呢?这就有了StartingWindow(也称之为PreviewWindow)的出现,这样看起来就像Activity已经启动起来了,只是数据内容还没有初始化好。

StartingWindow一般出现在应用程序进程创建并初始化成功前,所以它是个临时窗口,对应的WindowType是TYPE_APPLICATION_STARTING。目的是告诉用户,系统已经接受到操作,正在响应,在程序初始化完成后实现目的UI,同时移除这个窗口。

这个StartingWindow就是我们要讨论的白屏和黑屏的“元凶”,一般情况下我们会对Application和Activity设置Theme,系统会根据设置的Theme初始化StartingWindow。Window布局的顶层是DecorView,StartingWindow显示一个空DecorView,但是会给这个DecorView应用这个Activity指定的Theme,如果这个Activity没有指定Theme就用Application的Theme。

黑屏和白屏

在Theme中可以指定窗口的背景,Activity的ICON,APP整体文字颜色等,如果说没有指定任何属性,就会用默认的属性,也就是上文中提到的空DecorView,所以我们的白屏和黑屏和空DecorView息息相关,我们给APP设置的Style就决定了是白屏还是黑屏。

如果选择了Black的系列的主题那么Activity跳转的时候就是黑屏:

@android:style/Theme.Black"

如果选择了Light的系列的主题那么Activity跳转的时候就是白屏:

@android:style/Theme.Light"

解决方案

1. 设置透明主题

从主题入手 ,先说一下demo中用到的App主题

 <!-- Base application theme. -->
    <style name="public_app_theme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/public_white</item>
        <item name="colorPrimaryDark">@color/public_white</item>
        <item name="colorAccent">@color/public_text_black_deep</item>
        <item name="colorButtonNormal">@color/public_bg_button</item>
        <item name="android:textColorPrimary">@color/public_text_black_deep</item>
        <item name="colorControlHighlight">@color/public_bg_default_hint</item>
        <item name="alertDialogTheme">@style/public_dialog_alert</item>
        <item name="buttonStyle">@style/Widget.AppCompat.Button</item>
    </style>

关于colorPrimary、colorPrimaryDark 等属性,这里就不做讲解了。

关于启动页 SplashActivity的主题,基于不同版本的SDK有两种设置。

在基础版本的 styles 中使用

<!--     防止冷启动白屏-->
    <style name="public_app_theme_noBar" parent="public_app_theme">
        <!-- Customize your theme here. -->
        <item name="android:windowBackground">@drawable/app_splash_bg</item>
        <item name="android:windowFullscreen">true</item>
    </style>

在v21版本(即android 5.0)中为了防止虚拟按键被占用,在 styles 中使用

 <style name="public_app_theme_noBar" parent="public_app_theme">
        <item name="android:windowBackground">@drawable/app_splash_bg</item>
        <item name="android:windowFullscreen">true</item>
         <!-- 防止虚拟按键被占用 -->
        <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>

二者的资源地址如下图
在这里插入图片描述

2. 设置主题中的drawable

style中使用到的drawable也是两个文件

文件路径
在这里插入图片描述
drawable 路径下的 app_splash_bg.xml,第一个item是当前布局的背景,第二是需要显示的drawable以及显示位置。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 背景颜色 -->
    <!--白色矩形 作为背景色-->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/public_bg_default" />
        </shape>
    </item>

    <!--单独的slogan图片 并且设置下间距-->
    <item
        android:bottom="@dimen/public_height_50dp">
        <!--位置设置成靠下-->
        <bitmap
            android:gravity="bottom"
            android:src="@drawable/app_ic_launcher" />
    </item>


</layer-list>

drawable-v23文件下的app_splash_bg.xml,v23版本后可以设置layer-list中item的 width 和 height 属性。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 背景颜色 -->
    <!--白色矩形 作为背景色-->
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@color/public_bg_default" />
        </shape>
    </item>

    <!--单独的slogan图片 并且设置下间距-->
    <item
        android:width="@dimen/public_height_50dp"
        android:height="@dimen/public_height_50dp"
        android:bottom="@dimen/public_height_50dp"
        android:gravity="bottom|center_horizontal">
        <bitmap
            android:gravity="fill_horizontal|fill_vertical"
            android:src="@drawable/app_ic_launcher" />
    </item>


</layer-list>

项目地址

目前项目是在我的开源组件化框架中插入的,没有进行筛选,所以可能会给大家查找带来不便,希望谅解。欢迎 star 我的开源 框架base,是基于 JessYan的开源框架mvpArms和ArmsComponent基础上二次开发的。

https://github.com/alinainai/Base/tree/master/app/src/main/res

OK,到此结束。

发布了206 篇原创文章 · 获赞 68 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u013728021/article/details/103346243