最終效果圖:
ps:
這個圖片大小真的調不來吊输。。激率,如果太影響閱讀可移步至Demo
README
前言
最近想實現(xiàn)一個啟動頁咳燕,于是試了手機里的幾個常用App
,總結出以下需要實現(xiàn)的要點或注意點:
-
啟動優(yōu)化
一般情況下乒躺,冷啟動時在Application
初始化的過程中會出現(xiàn)短暫的白屏或黑屏招盲,這里可以做一個優(yōu)化,提高用戶體驗嘉冒。 -
固定屏幕方向
經測試曹货,大多數(shù)的應用(宇宙條除外),其啟動頁都是僅支持豎屏展示的讳推,如果橫屏展示的圖片會被拉伸顶籽,影響美觀。 -
開屏廣告 —— 異形屏全屏適配(劉海屏银觅,水滴屏等)
通常啟動頁都會有一個開屏頁廣告礼饱,需要占據通知欄的,一般情況下只需要設置一個全屏主題即可解決究驴,但是當碰到異形屏(如 水滴屏镊绪,劉海屏等)時就需要做一些額外的適配工作。 - 虛擬的導航欄遮蓋問題
如果存在虛擬NavigationBar
纳胧,那么還需要做一個適配镰吆,否則默認情況下,啟動頁的底部如果有文字或圖片的話會被虛擬的導航欄遮蓋住跑慕。 -
屏蔽Back鍵
即展示啟動頁時back
無效万皿,但是可以按home
鍵返回桌面摧找。
ok,明白了需求牢硅,下面開始實際操作:
基本實現(xiàn)
首先我們先來實現(xiàn)一個基礎版本蹬耘,然后再一點一點的進行優(yōu)化。
由于最近在學習架構組件减余,所以Demo
是基于MVVM
實現(xiàn)的综苔,不過對于本文的內容并沒有什么影響。
- 自定義定義全屏主題
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>
- 定義我們的啟動頁
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>
-
layout
文件就不上了位岔,通過效果圖就能看出來如筛,就只是放了一張圖片。
效果圖(Pixel
):
可以看到有很明顯的白屏抒抬。
啟動優(yōu)化
這里的啟動優(yōu)化杨刨,其實是給啟動時的白屏添加一個背景,這樣用戶在使用時是無感知的擦剑,從來造成一種啟動很快的錯覺妖胀。
-
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>
- 在全屏主題
AppTheme.Splash
設置上我們自定義的背景:
<style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
...
<!-- 設置window背景 -->
<item name="android:windowBackground">@drawable/layer_launcher</item>
</style>
- 設置了
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):
ok惠勒,可以看到赚抡,設置了背景之后感覺好多了,只不過這里為了更好的辨別添加了一個大紅色的TextView
可能看起來還是比較突兀纠屋。 = =
ps:
如果你的背景圖片被拉伸變形了涂臣,可以嘗試把圖片資源轉移到 drawable-xxhdpi
文件下。
固定屏幕方向 —— 強制豎屏
這個簡單巾遭,其實就是在AndroidManifest.xml
中給SplashActivity
設置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>
異形屏全屏適配
首先我們先來看看當前所實現(xiàn)的代碼在水滴屏上的效果(XiaoMi CC9e):
可以看到,屏幕上方有一個小黑條灼舍,所以對于異型屏吼和,我們需要進行額外的適配,這些適配可以分為兩種:
-
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劉海屏機型的劉海區(qū)域 -->
<meta-data
android:name="android.max_aspect"
android:value="2.2" />
<!-- 允許繪制到華為劉海屏機型的劉海區(qū)域 -->
<meta-data
android:name="android.notch_support"
android:value="true" />
<!-- 允許繪制到小米劉海屏機型的劉海區(qū)域 -->
<meta-data
android:name="notch.config"
android:value="portrait" />
</activity>
全屏適配
你以為這樣就真的OK了嗎鬼店? too young too simple !,先來上面的方案執(zhí)行后的效果(XiaoMi CC9e):
之前的小黑條變成白條了,說明我們前面做的適配是生效了的黔龟,但是我們的
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):
被虛擬NavigationBar
遮擋問題
先來看一下當前代碼在Pixel
上的運行情況:
可以看到我們的
logo
被虛擬的導航欄遮蓋住了,這時候需要在全屏主題中添加以下屬性:
<style name="AppTheme.Splash" parent="Theme.AppCompat.Light.NoActionBar">
...
<!-- 在5.0后观谦,增加了一個windowDrawsSystemBarBackgrounds屬性拉盾,用來標志此窗口是否負責繪制系統(tǒng)欄背景,
我們把它設成false豁状,這樣當它繪制windowBackground的時候,就會在NavigationBar之上倒得。-->
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>
同樣的泻红,需要在 values-v21
和 values-v28
下的styles.xml
中都加上。
效果圖(pixel):
屏蔽Back鍵
重寫SplashActivity
的 onBackPressed
方法什么都不做即可:
public class SplashActivity extends AppCompatActivity {
...
@Override
public void onBackPressed() {
//屏蔽back鍵
}
}
最后
原來一個啟動頁就有這么多的東西在里面霞掺。谊路。
Demo
中肯定還有沒有適配到的地方,如果發(fā)現(xiàn)文中哪里有錯或不足歡迎指正~菩彬。