前言
項(xiàng)目中我們通常將啟動(dòng)Activity命名為SplashActivity,并設(shè)置全屏,稍許停頓后再跳轉(zhuǎn)LoginActivity或者MainActivity等非全屏Activity(后面統(tǒng)稱為NormalActivity)。但是在跳到新界面的瞬間,狀態(tài)欄生硬地從內(nèi)容區(qū)擠出空間,插入在屏幕頂端,造成頁(yè)面出現(xiàn)一次蜜汁卡頓。事故現(xiàn)場(chǎng):

一般實(shí)踐
Google后可以找到一些解決方案,其中主要圍繞這篇文章《Switching-from-Full-Screen-to-Non-Full-Screen-Smoothly-in-Android》的思想。總結(jié)一下,首先在onCreate()中調(diào)用setContentView()之前插入兩行代碼:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
這樣做起到的效果是內(nèi)容區(qū)會(huì)一直延伸到屏幕頂部,狀態(tài)欄蓋在內(nèi)容區(qū)上面。如圖:

然后,只需要想辦法讓內(nèi)容區(qū)回到原來(lái)的高度,避免和狀態(tài)欄重疊。
拓展:
如果有小伙伴跟我一樣還不熟悉setContentView()背后的布局層次,可以閱讀《Android DecorView淺析》這篇博客,能幫你快速地了解。我在此借用了原博的一張圖,謝過(guò)博主。
DecorView的層次結(jié)構(gòu).png
結(jié)合拓展,想必大家已經(jīng)有還原內(nèi)容區(qū)的思路了。我的總結(jié)如下:
- 為頂部控件(
ToolBar、TitleBar或自定義View)設(shè)置paddingTop,值為狀態(tài)欄高度; - 通過(guò)
findViewById(android.R.id.content))得到編號(hào)21FrameLayout的實(shí)例,設(shè)置其marginTop,值為狀態(tài)欄高度; - 手動(dòng)new一個(gè)高為狀態(tài)欄高度view,利用編號(hào)1的
LinearLayout的addView()方法add到0位置上; - 手動(dòng)new一個(gè)高為狀態(tài)欄高度view,add到由編號(hào)21
FrameLayout.addView(),然后為我們的contentView設(shè)置MarginTop,高度為狀態(tài)欄高度。
獲取狀態(tài)欄高度的方法:
int resId = getResources().getIdentifier("status_bar_height", "dimen", "android");
int statusBarHeight = getResources().getDimensionPixelSize(resId);
// getResources()也可以替換為Resources.getSystem(),這樣的好處是不受Context的限制,從而可在任意地方調(diào)用
經(jīng)試驗(yàn)以上方法均能夠解決Activity跳轉(zhuǎn)卡頓的問(wèn)題。然鵝,主要在適配方面又會(huì)造成新的困擾(開發(fā)5分鐘,適配兩小時(shí) (? _ ?))。
- 如果你的應(yīng)用采用了沉浸狀態(tài)欄設(shè)計(jì),但狀態(tài)欄顏色和
ToolBar顏色不完全一致(比如微信),使用方法1會(huì)造成整體設(shè)計(jì)風(fēng)格被破壞。 - 方法2較方法1看上去差不多,然而,一些國(guó)內(nèi)的ROM(如Flyme)系統(tǒng)可以自動(dòng)幫你的App實(shí)現(xiàn)沉浸狀態(tài)欄(即使你什么都沒(méi)做)可謂非常先進(jìn)和人性化。但是設(shè)置margin后有可能看到的狀態(tài)欄背景和狀態(tài)圖標(biāo)顏色幾乎相近,既分辨不出圖標(biāo)又相當(dāng)難看。
- 方法3、4的方式更為靈活,就是稍微麻煩一點(diǎn)。
最佳實(shí)踐
我們費(fèi)盡心思在NormalActivity上做文章,結(jié)果到頭來(lái)發(fā)現(xiàn)還會(huì)遇到適配這個(gè)坑,累覺(jué)不愛啊!前面扯了那么多,終歸一句話:太!麻!煩!了!
所以重點(diǎn)來(lái)了。在SplashActivity中有沒(méi)有文章可做呢?嘿嘿,當(dāng)然是有的,而且思想非常簡(jiǎn)單:
設(shè)置SplashActivity為全屏,跳轉(zhuǎn)其他Activity前退出全屏模式。
第一步,設(shè)置SplashActivity全屏
方法1:AndroidManifest注冊(cè)全屏(AppCompat)
AndroidManifest.xml
<activity
android:name=".SplashActivity"
android:theme="@style/AppFullScreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
style.xml
<style name="AppFullScreenTheme" parent="@style/Theme.AppCompat.Light">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
方法2:在Activity的onCreate()中,調(diào)用setContentView()之前調(diào)用
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
第二步,在finish()之前調(diào)用
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
最終效果:

