一柬帕、前言
Android 開發(fā)過程中啟動頁是必不可少的哟忍,但是我們經(jīng)常會看到啟動打開后是先白屏或者黑屏,然后才會顯示出啟動頁的圖片陷寝,本文會解析此現(xiàn)象的原因锅很,以及給出解決方案
1.1 啟動白屏或黑屏的原因
AndroidManifest.xml
中的application
標(biāo)簽中設(shè)置了theme,當(dāng)設(shè)置的theme是Light
類型時啟動白屏凤跑,當(dāng)設(shè)置theme是Dark
類型時啟動黑屏爆安;
1.2 進(jìn)一步分析
當(dāng)系統(tǒng)啟動一個app時,zygote進(jìn)程會fork一個app子進(jìn)程仔引,進(jìn)程創(chuàng)建后在啟動activity時就會創(chuàng)建一個window
扔仓,這個window會使用theme
中設(shè)置的windowBackground來顯示背景顏色或者圖片,當(dāng)使用Light
或Dark
時跟進(jìn)代碼就能看到默認(rèn)設(shè)置的windowBackground
就是白色和黑色咖耘。
二翘簇、啟動頁--常規(guī)做法
2.1 創(chuàng)建Activity:SplashActivity
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
Handler().postDelayed({
startActivity(Intent(this,MainActivity::class.java))
finish()
},3000)
}
}
2.2 給啟動頁創(chuàng)建background:splash_background.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white"/>
<item>
<bitmap android:gravity="center"
android:src="@drawable/splash_screen"/>
</item>
</layer-list>
下面重點(diǎn)說下bitmap的屬性功能:
-
android:antialias
布爾值。啟用或停用抗鋸齒儿倒。
-
android:dither
布爾值版保。當(dāng)位圖的像素配置與屏幕不同時(例如:ARGB 8888 位圖和 RGB 565 屏幕),啟用或停用位圖抖動夫否。
-
android:filter
布爾值彻犁。啟用或停用位圖過濾。當(dāng)位圖收縮或拉伸以使其外觀平滑時使用過濾凰慈。
-
android:gravity
定義位圖的重力汞幢。重力指示當(dāng)位圖小于容器時,可繪制對象在其容器中放置的位置溉瓶。
必須是以下一個或多個(用 '|' 分隔)常量值:
值 說明 top
將對象放在其容器頂部急鳄,不改變其大小。 bottom
將對象放在其容器底部堰酿,不改變其大小疾宏。 left
將對象放在其容器左邊緣,不改變其大小触创。 right
將對象放在其容器右邊緣坎藐,不改變其大小。 center_vertical
將對象放在其容器的垂直中心哼绑,不改變其大小岩馍。 fill_vertical
按需要擴(kuò)展對象的垂直大小,使其完全適應(yīng)其容器抖韩。 center_horizontal
將對象放在其容器的水平中心蛀恩,不改變其大小。 fill_horizontal
按需要擴(kuò)展對象的水平大小茂浮,使其完全適應(yīng)其容器双谆。 center
將對象放在其容器的水平和垂直軸中心,不改變其大小席揽。 fill
按需要擴(kuò)展對象的垂直大小顽馋,使其完全適應(yīng)其容器。這是默認(rèn)值幌羞。 clip_vertical
可設(shè)置為讓子元素的上邊緣和/或下邊緣裁剪至其容器邊界的附加選項(xiàng)寸谜。裁剪基于垂直重力:頂部重力裁剪上邊緣,底部重力裁剪下邊緣属桦,任一重力不會同時裁剪兩邊熊痴。 clip_horizontal
可設(shè)置為讓子元素的左邊和/或右邊裁剪至其容器邊界的附加選項(xiàng)。裁剪基于水平重力:左邊重力裁剪右邊緣地啰,右邊重力裁剪左邊緣愁拭,任一重力不會同時裁剪兩邊。 -
android:mipMap
布爾值亏吝。啟用或停用 mipmap 提示岭埠。如需了解詳細(xì)信息,請參閱
setHasMipMap()
蔚鸥。默認(rèn)值為 false惜论。 -
android:tileMode
定義平鋪模式。當(dāng)平鋪模式啟用時止喷,位圖會重復(fù)馆类。重力在平鋪模式啟用時將被忽略。
必須是以下常量值之一:
值 說明 disabled
不平鋪位圖弹谁。這是默認(rèn)值乾巧。 clamp
當(dāng)著色器繪制范圍超出其原邊界時復(fù)制邊緣顏色 repeat
水平和垂直重復(fù)著色器的圖像句喜。 mirror
水平和垂直重復(fù)著色器的圖像,交替鏡像圖像以使相鄰圖像始終相接沟于。
2.3 給啟動頁創(chuàng)建style:SplashTheme
<style name="SplashTheme" parent="AppTheme">
<item name="windowNoTitle">true</item><!--無標(biāo)題-->
<item name="android:windowFullscreen">true</item><!--全屏-->
<item name="android:windowIsTranslucent">true</item><!--半透明-->
<item name="android:windowBackground">@drawable/splash_background</item>
</style>
2.4 在AndroidManifest.xml中給SplashActivity設(shè)置style
<activity android:name=".SplashActivity"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
通過上面的4步設(shè)置就能夠解決打開app白屏或黑屏的問題了咳胃。
三、最佳實(shí)踐
3.1 場景1:只有屏幕中間有一張圖片或者是圖片+文字
通過上面的方式就能實(shí)現(xiàn)旷太,注意bitmap使用gravity
為center
讓圖片和文字居中
顯示
3.2 場景2:屏幕中部和底部都有圖片或者文字
這種上下布局的展懈,例如微博,可以把圖片切成上下兩個供璧,或者切割圖片上下左右使圖片整體能夠居中顯示
方式一:將圖片切成屏幕中央顯示的圖片和底部圖片
splash_background.xml中就需要換種寫法了
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 整體的背景顏色 -->
<item>
<color android:color="@color/white"/>
</item>
<!-- 頂部 -->
<item>
<bitmap android:gravity="center"
android:src="@drawable/splash_center"/>
</item>
<!-- 底部 -->
<item>
<bitmap android:gravity="bottom|center_horizontal"
android:src="@drawable/splash_bottom"/>
</item>
</layer-list>
當(dāng)手機(jī)底部有虛擬導(dǎo)航欄時存崖,底部圖片會被遮擋,使導(dǎo)航欄透明即可:
class SplashActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
Handler().postDelayed({
startActivity(Intent(this,MainActivity::class.java))
finish()
},3000)
}
}
這句window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)是關(guān)鍵
方式二:將圖片設(shè)置成background而不是windowBackground
- style設(shè)置:
<style name="SplashTheme" parent="AppTheme">
<item name="windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/white</item>
<item name="android:background">@drawable/splash_background</item>
</style>
用background來設(shè)置背景圖片
- splash_background.xml設(shè)置:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white"/>
<item>
<bitmap android:gravity="clip_vertical|clip_horizontal"
android:src="@drawable/splash_screen"/>
</item>
</layer-list>
利用bitmap的gravity屬性睡毒,用clip_vertical|clip_horizontal來裁剪圖片
注意:利用第二種方式時不能使用window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)来惧,這個會導(dǎo)致圖片被拉伸