Android启动页实现(启动优化,刘海屏水滴屏全屏适配等)

最终效果图

image

ps

这个图片大小真的调不来。。,如果太影响阅读可移步至DemoREADME

前言

最近想实现一个启动页,于是试了手机里的几个常用App,总结出以下需要实现要点注意点

  1. 启动优化

    一般情况下,冷启动时在Application初始化的过程中会出现短暂的白屏或黑屏,这里可以做一个优化,提高用户体验。
  2. 固定屏幕方向

    经测试,大多数的应用(宇宙条除外),其启动页都是仅支持竖屏展示的,如果横屏展示的图片会被拉伸,影响美观。
  3. 开屏广告 —— 异形屏全屏适配(刘海屏,水滴屏等)

    通常启动页都会有一个开屏页广告,需要占据通知栏的,一般情况下只需要设置一个全屏主题即可解决,但是当碰到异形屏(如 水滴屏,刘海屏等)时就需要做一些额外的适配工作。
  4. 虚拟的导航栏遮盖问题

    如果存在虚拟NavigationBar,那么还需要做一个适配,否则默认情况下启动页的底部如果有文字或图片的话会被虚拟的导航栏遮盖住
  5. 屏蔽Back键

    即展示启动页时back无效,但是可以按home键返回桌面。



ok,明白了需求,下面开始实际操作:

基本实现

首先我们先来实现一个基础版本,然后再一点一点的进行优化
由于最近在学习架构组件,所以Demo是基于MVVM实现的,不过对于本文的内容并没有什么影响。

  1. 自定义定义全屏主题 AppTheme.Splash
<!--全屏主题-->
<style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowContentOverlay">@null</item>
    <!-- 设置window过度效果 禁用窗口的预览动画 -->
    <item name="android:windowDisablePreview">false</item>
</style>
  1. 定义我们的启动页 SplashActivity 并在AndroidManifest.xml设置上自定义的全屏主题
public class SplashActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivitySplashBinding mBinding =
                DataBindingUtil.setContentView(this, R.layout.activity_splash);

        //2s延迟后进入MainActivity
        new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
                finish();
            }
        }, 2000);
    }
}
<activity 
    android:theme="@style/AppTheme.Splash"
    android:name=".splash.SplashActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
  1. layout文件就不上了,通过效果图就能看出来,就只是放了一张图片。

效果图(Pixel):

image

可以看到有很明显的白屏

启动优化

这里的启动优化,其实是给启动时的白屏添加一个背景,这样用户在使用时是无感知的,从来造成一种启动很快的错觉。

  1. drawable 文件夹下面制作背景图片layer_launcher.xml
<?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="#FFF" />
        </shape>
    </item>

    <item android:bottom="25dp">
        <bitmap
            android:gravity="bottom|center_horizontal"
            android:src="@drawable/ic_launcher" />
    </item>
</layer-list>
  1. 全屏主题AppTheme.Splash设置上我们自定义的背景
<style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <!-- 设置window背景 -->
    <item name="android:windowBackground">@drawable/layer_launcher</item>
</style>
  1. 设置了window的背景之后,启动页就可以不设置图片了
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
           
        <TextView
            android:gravity="center"
            android:text="splash activity"
            android:background="#F00"
            android:layout_marginBottom="120dp"
            android:layout_gravity="center_horizontal"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <!-- <View-->
        <!--    android:layout_width="match_parent"-->
        <!--    android:layout_height="0dp"-->
        <!--    android:layout_weight="1" />-->
        
        <!-- <ImageView-->
        <!--    android:layout_width="80dp"-->
        <!--    android:layout_height="80dp"-->
        <!--    android:layout_gravity="center_horizontal|bottom"-->
        <!--    android:layout_marginBottom="30dp"-->
        <!--    android:scaleType="fitXY"-->
        <!--    android:src="@drawable/ic_launcher" />-->

    </LinearLayout>
</layout>

效果图(RedMi 3S):

image

ok,可以看到,设置了背景之后感觉好多了,只不过这里为了更好的辨别添加了一个大红色的TextView可能看起来还是比较突兀。 = =

ps:

如果你的背景图片被拉伸变形了,可以尝试把图片资源转移到 drawable-xxhdpi 文件下。

固定屏幕方向 —— 强制竖屏

这个简单,其实就是在AndroidManifest.xmlSplashActivity设置screenOrientation属性为 portrait 即可。

<activity
    android:name=".splash.SplashActivity"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.Splash">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

异形屏全屏适配

首先我们先来看看当前所实现的代码在水滴屏上的效果(XiaoMi CC9e):

image



可以看到,屏幕上方有一个小黑条,所以对于异型屏,我们需要进行额外的适配,这些适配可以分为两种

  • Android P(9.0)及以上的手机,Google官方给我们提供了解决方案
  • Android O(8.0)及以下的手机,由于这时没有官方的适配方案,所以只能根据具体的机型去查看相应厂商给我们提供的解决文档了。

Android P 适配

根据文档,我们只需要在全屏主题中再添加一个windowLayoutInDisplayCutoutMode属性并且值为 shortEdges 即可,只不过由于是Android P才出的,所以需要复制一份主题到values-v28/styles.xml中并设置上该属性:

<!-- values-v28/styles.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    ...
    
    <style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
       
       ...
       
       <!-- Android P 异性屏适配 可以达到全面屏的效果 -->
       <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
    </style>
</resources>

Android O 适配

很遗憾,设备资源有限,手上的真机只有一部红米3S小米CC9e(水滴屏 Android Q),完美的避开了这种情况。 = =

不过我有在某个博客中(原谅我找不到了原博客链接了)看到了解决方案(未验证),需要的小伙伴的可以顺便验证一下:

<activity
    android:name=".splash.SplashActivity"
    android:screenOrientation="portrait"
    android:theme="@style/AppTheme.Splash">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <!--允许绘制到oppo、vivo刘海屏机型的刘海区域 -->
    <meta-data
        android:name="android.max_aspect"
        android:value="2.2" />

    <!-- 允许绘制到华为刘海屏机型的刘海区域 -->
    <meta-data
        android:name="android.notch_support"
        android:value="true" />

    <!-- 允许绘制到小米刘海屏机型的刘海区域 -->
    <meta-data
        android:name="notch.config"
        android:value="portrait" />
</activity>

全屏适配

你以为这样就真的OK了吗too young too simple !,先来上面的方案执行后的效果(XiaoMi CC9e):

image

之前的小黑条变成白条了,说明我们前面做的适配是生效了的,但是我们的TextView并没有延伸要屏幕顶部,下面是解决方案:

在全屏主题中添加以下两个属性即可,注意这两条属性是API 21出来的,所以需要新建values-v21/styles.xml,别忘了之前添加的values-v28/styles.xml中也要加上:

<!-- values-v21/styles.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    ...

    <style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
            
        ...
        
        <!-- 设置statusBarColor 为透明-->
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    
    </style>
</resources>

效果图(XiaoMi CC9e):

image

被虚拟NavigationBar遮挡问题

先来看一下当前代码在Pixel上的运行情况:

image



可以看到我们的logo被虚拟的导航栏遮盖住了,这时候需要在全屏主题中添加以下属性:

<style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
     
     ...
     
    <!-- 在5.0后,增加了一个windowDrawsSystemBarBackgrounds属性,用来标志此窗口是否负责绘制系统栏背景,
    我们把它设成false,这样当它绘制windowBackground的时候,就会在NavigationBar之上。-->
    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>

同样的,需要在 values-v21values-v28 下的styles.xml都加上

效果图(pixel):

image


屏蔽Back键

重写SplashActivityonBackPressed 方法什么都不做即可:

public class SplashActivity extends AppCompatActivity {

    ...

    @Override
    public void onBackPressed() {
        //屏蔽back键
    }
}

最后

Demo链接

原来一个启动页就有这么多的东西在里面。。

Demo中肯定还有没有适配到的地方,如果发现文中哪里有错或不足欢迎指正~

参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352