成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Android 沉浸式解析和輪子使用

bingo / 1126人閱讀

摘要:前言我們先一起來回顧一下實(shí)現(xiàn)沉浸式狀態(tài)欄的一般套路。從以上版本才是真正的可以設(shè)置沉浸式體驗(yàn),但也僅僅是操作狀態(tài)欄和導(dǎo)航欄的顯示與隱藏。屬性解釋設(shè)置了表明會負(fù)責(zé)系統(tǒng)的繪制,繪制透明背景的系統(tǒng)狀態(tài)欄和導(dǎo)航欄,然后用和的顏色填充相應(yīng)的區(qū)域。

前言

我們先一起來回顧一下實(shí)現(xiàn)沉浸式狀態(tài)欄的一般套路。在Android上,關(guān)于對StatusBar(狀態(tài)欄)的操作,一直都在不斷改善,并且表現(xiàn)越來越好,在Android4.4 以下,我們可以對StatusBar和 NavigationBar進(jìn)行顯示和隱藏操作。但是直到Android4.4,我們才能真正意義上的實(shí)現(xiàn)沉浸式狀態(tài)欄。從Android4.4 到現(xiàn)在(Android 9),關(guān)于沉浸式大概可以分成三個階段:

Android4.4(API 19) - Android 5.0(API 21): 這個階段可以實(shí)現(xiàn)沉浸式,但是表現(xiàn)得還不是很好,實(shí)現(xiàn)方式為: 通過FLAG_TRANSLUCENT_STATUS設(shè)置狀態(tài)欄為透明并且為全屏模式,然后通過添加一個與StatusBar 一樣大小的View,將View 的 background 設(shè)置為我們想要的顏色,從而來實(shí)現(xiàn)沉浸式。

Android 5.0(API 21)以上版本: 在Android 5.0的時候,加入了一個重要的屬性和方法 android:statusBarColor (對應(yīng)方法為 setStatusBarColor),通過這個方法我們就可以輕松實(shí)現(xiàn)沉浸式。也就是說,從Android5.0開始,系統(tǒng)才真正的支持沉浸式。

Android 6.0(API 23)以上版本:其實(shí)Android6.0以上的實(shí)現(xiàn)方式和Android 5.0 +是一樣,為什么要將它歸為一個多帶帶重要的階段呢?是因?yàn)閺腁ndroid 6.0(API 23)開始,我們可以改狀態(tài)欄的繪制模式,可以顯示白色或淺黑色的內(nèi)容和圖標(biāo)(除了魅族手機(jī),魅族自家有做源碼更改,6.0以下就能實(shí)現(xiàn))。

總結(jié):這三個階段的Android上API版本混亂,各種Flag林立。再加上各大廠商的定制化可謂是火上澆油,讓安卓開發(fā)者異常頭疼。

1.沉浸式三個階段使用

我們將從沉浸式支持的三個階段和支持的功能出發(fā),去了解出現(xiàn)的相關(guān)背景,然后去了解怎么實(shí)現(xiàn)三個階段的沉浸式。

1.1 Android4.0-Android5.0設(shè)置沉浸體驗(yàn)

在android4.4及以上版本中為 setSystemUiVisibility() 方法引入了一個新的flag:SYSTEM_UI_FLAG_IMMERSIVE,它可以使你的app實(shí)現(xiàn)真正意義上的全屏體驗(yàn)。當(dāng)SYSTEM_UI_FLAG_IMMERSIVE、SYSTEM_UI_FLAG_HIDE_NAVIGATION 和SYSTEM_UI_FLAG_FULLSCREEN三個flag一起使用的時候,可以隱藏狀態(tài)欄與導(dǎo)航欄,同時讓你的app可以捕捉到用戶的所有觸摸屏事件。從Android4.4以上版本才是真正的可以設(shè)置沉浸式體驗(yàn),但也僅僅是操作狀態(tài)欄和導(dǎo)航欄的顯示與隱藏。

1.1.1 FLAG_TRANSLUCENT_STATUS

當(dāng)沉浸式全屏模式啟用的時候,你的activity會繼續(xù)接受各類的觸摸事件。用戶可以通過在狀態(tài)欄與導(dǎo)航欄原來區(qū)域的邊緣向內(nèi)滑動讓系統(tǒng)欄重新顯示。這個操作清空了SYSTEM_UI_FLAG_HIDE_NAVIGATIONSYSTEM_UI_FLAG_FULLSCREEN,如果沒有兩個標(biāo)志的話,系統(tǒng)欄重新變得可見。如果設(shè)置了兩個標(biāo)簽的話,這個操作同時也觸發(fā)了View.OnSystemUiVisibilityChangeListener。然而, 如果你想讓系統(tǒng)欄在一段時間后自動隱藏的話,你應(yīng)該使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY標(biāo)簽

展示了各種不同的“沉浸式”狀態(tài)

在上圖中:

非沉浸模式 —— 展示了應(yīng)用進(jìn)入沉浸模式之前的狀態(tài)。也展示了設(shè)置IMMERSIVE標(biāo)簽后用戶滑動展示系統(tǒng)欄的狀態(tài)。用戶滑動后,SYSTEM_UI_FLAG_HIDE_NAVIGATIONSYSTEM_UI_FLAG_FULLSCREEN就會被清除,系統(tǒng)欄就會重新顯示并保持可見。請注意,最好的方式就是讓所有的UI控件與系統(tǒng)欄的顯示隱藏保持同步,這樣可以減少屏幕顯示所處的狀態(tài),同時提供了更無縫平滑的用戶體驗(yàn)。因此所有的UI控件跟隨系統(tǒng)欄一同顯示。一旦應(yīng)用進(jìn)入了沉浸模式,UI控件也跟隨著系統(tǒng)欄一同隱藏。為了確保UI的可見性與系統(tǒng)欄保持一致,我們需要一個監(jiān)聽器View.OnSystemUiVisibilityChangeListener來監(jiān)聽系統(tǒng)欄的變化。這在下一節(jié)中將詳細(xì)講解。

提示氣泡——第一次進(jìn)入沉浸模式時,系統(tǒng)將會顯示一個提示氣泡,提示用戶如何再讓系統(tǒng)欄顯示出來。請注意,如果為了測試你想強(qiáng)制顯示提示氣泡,你可以先將應(yīng)用設(shè)為沉浸模式,然后按下電源鍵進(jìn)入鎖屏模式,并在5秒中之后打開屏幕。

沉浸模式—— 這張圖展示了隱藏了系統(tǒng)欄和其他UI控件的狀態(tài)。你可以設(shè)置IMMERSIVE和IMMERSIVE_STICKY來進(jìn)入這個狀態(tài)。

粘性標(biāo)簽——這就是你設(shè)置了IMMERSIVE_STICKY標(biāo)簽時的UI狀態(tài),用戶會向內(nèi)滑動以展示系統(tǒng)欄。半透明的系統(tǒng)欄會臨時的進(jìn)行顯示,一段時間后自動隱藏。滑動的操作并不會清空任何標(biāo)簽,也不會觸發(fā)系統(tǒng)UI可見性的監(jiān)聽器,因?yàn)闀簳r顯示的導(dǎo)航欄并不被認(rèn)為是一種可見的狀態(tài)。

注意,immersive類的標(biāo)簽只有在與SYSTEM_UI_FLAG_HIDE_NAVIGATION,SYSTEM_UI_FLAG_FULLSCREEN中一個或兩個一起使用的時候才會生效。你可以只使用其中的一個,但是一般情況下你需要同時隱藏狀態(tài)欄和導(dǎo)航欄以達(dá)到沉浸的效果。

1.1.2 兩種使用這個屬性的方式:

在使用時候,我們通常需要考慮的是狀態(tài)欄一值顯示在頂部而不會隱藏或者被遮擋(其他app情況如:讀書app或者是游戲app則需要隱藏頂部狀態(tài)欄),所以只需要通過代碼設(shè)置FLAG_TRANSLUCENT_STATU

 
 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

通過主題theme設(shè)置屬性windowTranslucentStatus:

    

效果如下:

效果如上圖,可以看出,沉浸式的效果是出來了,但是也有一個問題,我們的標(biāo)題欄和狀態(tài)欄重疊了,相當(dāng)于整個布局上移了StatusBar 的高度。

為了讓標(biāo)題欄回到原來的位置并且適應(yīng)標(biāo)題欄的顏色,我們在標(biāo)題欄的上方添加一個大小和StatusBar大小一樣假的狀態(tài)欄View,View 的BackgroundColor 可以自己設(shè)置成標(biāo)題欄一樣的顏色也可以是其他顏色,這個View起到一個占位的作用。這個時候,標(biāo)題欄就會下移StatusBar的高度,回到正常的位置。

通過設(shè)置paddingTop重新繪制標(biāo)題欄高度代碼如下:

 View statusBarView = mDecorView.findViewById(IMMERSION_STATUS_BAR_VIEW);
        if (statusBarView == null) {
            statusBarView = new View(mActivity);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                    mBarConfig.getStatusBarHeight());
            params.gravity = Gravity.TOP;
            statusBarView.setLayoutParams(params);
            statusBarView.setVisibility(View.VISIBLE);
            statusBarView.setId(IMMERSION_STATUS_BAR_VIEW);
            mDecorView.addView(statusBarView);
        }
        if (mBarParams.statusBarColorEnabled) {
            statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                    mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));
        } else {
            statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                    Color.TRANSPARENT, mBarParams.statusBarAlpha));
        }

添加上述代碼后,效果如下:

通過以上就可以實(shí)現(xiàn)Android 4.4 上的沉浸式狀態(tài)欄。

小結(jié):Android4.4-Android5.0的步驟就是為window添加FLAG_TRANSLUCENT_STATUS的Flag,然后添加一個假的狀態(tài)欄,通過上述方法設(shè)置的沉浸式在Android4.4-Android5.0之間的效果如貼圖,狀態(tài)欄頂部是有一個黑色陰影漸變,在5.0版本版本以上被修復(fù)了。
如果是一張圖片沉浸到狀態(tài)欄則不需要設(shè)置這個假的狀態(tài)欄,只需要設(shè)置,F(xiàn)LAG_TRANSLUCENT_STATUS就OK。并且在Android4.4-Android5.0是沒有提供改變狀態(tài)顏色的屬性,所以只能通過新增加一個假的狀態(tài)欄方式改變背景顏色。
1.2 Android5.0以上設(shè)置狀態(tài)欄背景顏色

Android 5.0 是一個里程碑式的版本,從Android 5.0開始,Google 推出了全新的設(shè)計(jì)規(guī)范 Material Design,并且原生控件就可以實(shí)現(xiàn)一些炫酷的UI動效。從這個版本開始,google 加入了一個比較重要的方法setStatusBarColor (對應(yīng)屬性:android:statusBarColor),通過這個方法,可以很輕松地實(shí)現(xiàn)沉浸式狀態(tài)欄。方法如下

public abstract void setStatusBarColor(@ColorInt int color);

注意看這個方法的注釋,想要這個方法生效,必須還要配合一個Flag一起使用,必須設(shè)置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS ,并且不能設(shè)置FLAG_TRANSLUCENT_STATUS(Android 4.4才用這個),所以和4.4互斥不能共用。所以Android5.0以上可以設(shè)置狀態(tài)欄和導(dǎo)航欄字體顏色。

1.2.1 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS屬性

解釋:設(shè)置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,表明會Window負(fù)責(zé)系統(tǒng)bar的background 繪制,繪制透明背景的系統(tǒng)bar(狀態(tài)欄和導(dǎo)航欄),然后用getStatusBarColor()和getNavigationBarColor()的顏色填充相應(yīng)的區(qū)域。這就是Android 5.0 以上實(shí)現(xiàn)沉浸式導(dǎo)航欄的原理。

實(shí)現(xiàn)沉浸式添加如下代碼:

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //注意要清除 FLAG_TRANSLUCENT_STATUS flag
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));

效果如下:

如果在開發(fā)的時候是通過設(shè)置主題的方式設(shè)置,則需要在values-v21文件夾下添加如下主題,達(dá)到兼容目的
1.2.2 圖片延伸到狀態(tài)欄

在Android 5.0 使圖片延伸到狀態(tài)欄,只需設(shè)置windowTranslucentStatus,將 statusBarColor 設(shè)置為透明即可。
主題方式設(shè)置如下:

在開發(fā)過程中,使用代碼設(shè)置windowTranslucentStatus需要通過版本號的判斷兼容 Android5.0以下和Android 5.0以上。
1.3 Android 6.0 +實(shí)現(xiàn)狀態(tài)欄字色和圖標(biāo)淺黑色

使用Android6.0以下版本沉浸式的時候會遇到一個問題,那就是Android 系統(tǒng)狀態(tài)欄的字色和圖標(biāo)顏色為白色,當(dāng)狀態(tài)欄顏色接近淺色的時候,狀態(tài)欄上的內(nèi)容就看不清了。Android 6.0 新添加了一個屬性來解決這個問題,屬性是SYSTEM_UI_FLAG_LIGHT_STATUS_BAR。

1.3.1 SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

解釋:為setSystemUiVisibility(int)方法添加的Flag,請求status bar 繪制模式,它可以兼容亮色背景的status bar 。要在設(shè)置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDSflag ,同時清除了FLAG_TRANSLUCENT_STATUSflag 才會生效。

通過代碼設(shè)置:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

效果如下

并且還可以在主題中使用屬性,并且該主題需要放在values-v23文件夾下相應(yīng)Android6.0以上才能生效:

2. ZanImmersionBar輪子的原理和使用

在實(shí)際開發(fā)過程中,我們不僅僅只會遇到以上三種版本兼容問題,還需要考慮如:不同手機(jī)品牌,動態(tài)該狀態(tài)欄背景,以及Fragment中需要有自己的狀態(tài)欄顏色場景。所以需要綜合考慮多種場景,達(dá)到能適配多種開發(fā)情況的要求。
總結(jié)出以下場景:

綜合以上場景并且參考github例子進(jìn)行封裝之后得到了ZanImmersionBar這個輪子

2.1 原理:

我們希望將設(shè)置沉浸式效果都封裝在一個類里面,想達(dá)到所有的效果通過一個方法設(shè)置,但很多的效果中都會有重復(fù)的設(shè)置步驟,并且每個效果的方法太多則分不清使用哪個,所以將設(shè)置沉浸式效果拆分成幾個步驟,而想要設(shè)置個性效果,通過方法設(shè)置參數(shù),最后通過init方法收集所有參數(shù)讓后統(tǒng)一設(shè)置參數(shù)屬性。

ZanImmersionBar.with(this).init();//該方法將進(jìn)行以下步驟處理沉浸式
public void init() {
        //更新Bar的參數(shù)
        updateBarParams();
        //設(shè)置沉浸式
        setBar();
        //適配狀態(tài)欄與布局重疊問題
        fitsLayoutOverlap();
        //適配軟鍵盤與底部輸入框沖突問題
        fitsKeyboard();
        //變色view
        transformView();
    }

沉浸式設(shè)置流程如下圖:

這幾個步驟其中,獲取參數(shù)和設(shè)置沉浸式是必須經(jīng)過,下面三種設(shè)置是在開發(fā)中可能遇到的情況,也是設(shè)置參數(shù),如果匹配到了則會進(jìn)行三種設(shè)置的處理,接下來主要分析下第一個步驟和第二步驟。

2.1.1 收集bar參數(shù)

我們使用一個對象用于存儲用戶設(shè)置的bar參數(shù),這些參數(shù)有狀態(tài)欄和導(dǎo)航欄顏色、透明度、顯示隱藏等等,通過該對象中的參數(shù)來分別設(shè)置

public class BarParams implements Cloneable {
    /**
     * 狀態(tài)欄顏色
     */
    @ColorInt
    int statusBarColor = Color.TRANSPARENT;
    /**
     * 導(dǎo)航欄顏色
     */
    @ColorInt
    int navigationBarColor = Color.BLACK;
    /**
     * The Default navigation bar color.
     */
    int defaultNavigationBarColor = Color.BLACK;
    /**
     * 狀態(tài)欄透明度
     */
    @FloatRange(from = 0f, to = 1f)
    float statusBarAlpha = 0.0f;
    /**
     * 導(dǎo)航欄透明度
     */
    @FloatRange(from = 0f, to = 1f)
    float navigationBarAlpha = 0.0f;
      //等其他屬性
    ...
}

而這些屬性可以通過以下ZanImmersionBar提供的方法進(jìn)行個性化設(shè)置,而這些方法只是將需要設(shè)置的參數(shù)添加到BarParams對象中,最后必須調(diào)用init將參數(shù)設(shè)置上去。

 ZanImmersionBar.with(this)
             .transparentStatusBar()  //透明狀態(tài)欄,不寫默認(rèn)透明色
             .transparentNavigationBar()  //透明導(dǎo)航欄,不寫默認(rèn)黑色(設(shè)置此方法,fullScreen()方法自動為true)
             .transparentBar()             //透明狀態(tài)欄和導(dǎo)航欄,不寫默認(rèn)狀態(tài)欄為透明色,導(dǎo)航欄為黑色(設(shè)置此方法,fullScreen()方法自動為true)
             .statusBarColor(R.color.colorPrimary)     //狀態(tài)欄顏色,不寫默認(rèn)透明色
             .navigationBarColor(R.color.colorPrimary) //導(dǎo)航欄顏色,不寫默認(rèn)黑色
             .barColor(R.color.colorPrimary)  //同時自定義狀態(tài)欄和導(dǎo)航欄顏色,不寫默認(rèn)狀態(tài)欄為透明色,導(dǎo)航欄為黑色
             .statusBarAlpha(0.3f)  //狀態(tài)欄透明度,不寫默認(rèn)0.0f
             .navigationBarAlpha(0.4f)  //導(dǎo)航欄透明度,不寫默認(rèn)0.0F
             .barAlpha(0.3f)  //狀態(tài)欄和導(dǎo)航欄透明度,不寫默認(rèn)0.0f
             .statusBarDarkFont(true)   //狀態(tài)欄字體是深色,不寫默認(rèn)為亮色
             .navigationBarDarkIcon(true) //導(dǎo)航欄圖標(biāo)是深色,不寫默認(rèn)為亮色
                           //等一些其他方法
             .init();  //必須調(diào)用方可沉浸式

設(shè)置完參數(shù)后,則需要收集這些參數(shù),如果在Fragment中使用,則需要Activity同步Fragment的BarParams參數(shù)

//獲得Bar相關(guān)信息
//如果在Fragment中使用,讓Activity同步Fragment的BarParams參數(shù)
if (mIsFragment) {
    ZanImmersionBar immersionBar = mImmersionBarMap.get(mActivity.toString());
    if (immersionBar != null) {
        immersionBar.mBarParams = mBarParams;
    }
}

mImmersionBarMap是個Map,用于存儲每個Activity對應(yīng)的ZanImmersionBar對象

原理:其實(shí)我們通過沉浸式三代發(fā)展史,我們可以知道設(shè)置沉浸式都是通過改變Activity的window屬性達(dá)到沉浸式,所以我們想要在Fragment的定制化沉浸式,其實(shí)是通過改變Activity的BarParams參數(shù)再設(shè)置Activity的沉浸式,所以需要注意對Fragment設(shè)置沉浸式前必須保證加載Fragment的Activity先進(jìn)行了ZanImmersionBar的init初始化。

另例:需要注意dialogFragment和Dialog是有自己的window,該window是屬于所屬Activity的子window,所以設(shè)置dialogFragment和Dialog的沉浸式改變的是自己window里的屬性,而不是改變Actvity的window里的屬性。

關(guān)閉銷毀:在activity的onDestroy方法中執(zhí)行,因?yàn)閙ImmersionBarMap存儲了每個Activity對應(yīng)的ZanImmersionBar對象,所以當(dāng)Activity關(guān)閉了需要及時釋放,不然mImmersionBarMap會存在過多無用的ZanImmersionBar對象。

ZanImmersionBar.with(this).destroy(); //必須調(diào)用該方法,防止內(nèi)存泄漏
 public void destroy() {
        //取消監(jiān)聽
        cancelListener();
        //刪除當(dāng)前界面對應(yīng)的ImmersionBar對象
        Iterator> iterator = mImmersionBarMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = iterator.next();
            if (entry.getKey().contains(mImmersionBarName) || (entry.getKey().equals(mImmersionBarName))) {
                iterator.remove();
            }
        }
    }

2.1.2 初始化狀態(tài)欄和導(dǎo)航欄

? 該方法則是將上一步的參數(shù)進(jìn)行初始化,初始化過程則會根據(jù)沉浸式三個階段和不同廠商進(jìn)行區(qū)分設(shè)置。需要注意小米手機(jī)系統(tǒng)有自己定制化設(shè)置的屬性,所以需要分區(qū)設(shè)置

private void setBar() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !OSUtils.isEMUI3_x()) {
            //適配劉海屏
            fitsNotchScreen();
            //初始化5.0以上,包含5.0
            uiFlags = initBarAboveLOLLIPOP(uiFlags);
            //android 6.0以上設(shè)置狀態(tài)欄字體為暗色
            uiFlags = setStatusBarDarkFont(uiFlags);
            //android 8.0以上設(shè)置導(dǎo)航欄圖標(biāo)為暗色
            uiFlags = setNavigationIconDark(uiFlags);
        } else {
            //初始化5.0以下,4.4以上沉浸式
            initBarBelowLOLLIPOP();
        }
             ...    
    }
    if (OSUtils.isMIUI6Later()) {
        //修改miui狀態(tài)欄字體顏色
        setMIUIBarDark(mWindow, MIUI_STATUS_BAR_DARK, mBarParams.statusBarDarkFont);
        //修改miui導(dǎo)航欄圖標(biāo)為黑色
        if (mBarParams.navigationBarEnable) {
            setMIUIBarDark(mWindow, MIUI_NAVIGATION_BAR_DARK, mBarParams.navigationBarDarkIcon);
        }
    }
    ...
}

我們可以重點(diǎn)看下5.0以上狀態(tài)欄和導(dǎo)航欄初始化,設(shè)置初始化window屬性讓后設(shè)置導(dǎo)航欄和狀態(tài)欄顏色

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private int initBarAboveLOLLIPOP(int uiFlags) {
    //Activity全屏顯示,但狀態(tài)欄不會被隱藏覆蓋,狀態(tài)欄依然可見,Activity頂端布局部分會被狀態(tài)欄遮住。
    uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    //判斷是否存在導(dǎo)航欄
    if (mBarConfig.hasNavigationBar()) {
        mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
    }
    //需要設(shè)置這個才能設(shè)置狀態(tài)欄和導(dǎo)航欄顏色
    mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //設(shè)置狀態(tài)欄顏色
    if (mBarParams.statusBarColorEnabled) {
        mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));
    } else {
        mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                Color.TRANSPARENT, mBarParams.statusBarAlpha));
    }
      ...
    return uiFlags;
}

通過代碼分析可以看到其實(shí)ZanImmersionBar所做的事情就是將設(shè)置沉浸式方法進(jìn)行步驟拆分和增加個性屬性設(shè)置,并且將沉浸式三個階段和不同廠商進(jìn)行區(qū)分獨(dú)立方法設(shè)置調(diào)用。

2.2 建議和使用

建議在BaseActivity中初始化和銷毀

    public class BaseActivity extends AppCompatActivity {
  
         @Override
         protected void onCreate(@Nullable Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             // 所有子類都將繼承這些相同的屬性,請?jiān)谠O(shè)置界面之后設(shè)置
             ZanImmersionBar.with(this).init();  
         }
         @Override
         protected void onDestroy() {
             super.onDestroy();
             // 必須調(diào)用該方法,防止內(nèi)存泄漏
             ZanImmersionBar.with(this).destroy();  
         }
     }

展示Activity中使用效果

2.3在Fragment使用ZanImmersionBar

注意在Fragment中使用ZanImmersionBar需要在承載的Activity中初始化ZanImmersionBar,不然會拋出異常

    public abstract class BaseFragment{
         @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
             super.onViewCreated(view, savedInstanceState);
             initImmersionBar();
    }
         @Override
       public void initImmersionBar() {
            ZanImmersionBar.with(this).keyboardEnable(true).init();
        }
    }

具體的Fragment調(diào)用以下方法:

    @Override
    public void initImmersionBar() {
        super.initImmersionBar();
        ZanImmersionBar.with(this)
                .statusBarDarkFont(true)
                .statusBarColor(R.color.btn1)
                .navigationBarColor(R.color.btn1)
                .init();
    }

設(shè)置Fragment的狀態(tài)欄顏色和狀態(tài)欄字體顏色效果

2.4 在Dialog中實(shí)現(xiàn)沉浸式

在Dialog中設(shè)置ZanImmersionBar方式和在Fragment或者Activity一樣,如果在Fragment或者Activity中有設(shè)置并且dialog出現(xiàn)不需要改變狀態(tài)欄則不用設(shè)置ZanImmersionBar,如果需要做定制化上面的高級用法在Dialog也支持

結(jié)合dialogFragment中使用

      ZanImmersionBar.with(this).init();

其他dialog

      ZanImmersionBar.with(this, dialog).init();

2.5 在PopupWindow中實(shí)現(xiàn)沉浸式

重點(diǎn)是調(diào)用以下方法,但是此方法會導(dǎo)致有導(dǎo)航欄的手機(jī)底部布局會被導(dǎo)航欄覆蓋,還有底部輸入框無法根據(jù)軟鍵盤彈出而彈出。這個屬性在頂部彈出的時候是需要使用,如果是底部彈框需要看情況而定。

    popupWindow.setClippingEnabled(false);
2.6 狀態(tài)欄與布局頂部重疊解決方案,六種方案任選其一(可選)

正常使用ZanImmersionBar一般不需要考慮重疊問題但在項(xiàng)目中接入ZanImmersionBar并且頁面沒有考慮給頭部控件預(yù)留出狀態(tài)欄的高度,并且需要將頁面內(nèi)容沉浸到狀態(tài)欄或者做定制化狀態(tài)欄,這種情況下需要考慮重疊問題。之前說到Android4.4版本的時候解決重疊的方式是一種,也可以參考一下幾種方式解決狀態(tài)欄與布局頂部重疊問題。

① 使用dimen自定義狀態(tài)欄高度,不建議使用,因?yàn)樵O(shè)備狀態(tài)欄高度并不是固定的

在values-v19/dimens.xml文件下

        25dp

在values/dimens.xml文件下

        0dp

然后在布局界面添加view標(biāo)簽,高度指定為status_bar_height

       
       
           
       
           
       

② 使用系統(tǒng)的fitsSystemWindows屬性,使用該屬性不會導(dǎo)致輸入框與軟鍵盤沖突問題,不要再Fragment使用該屬性

       
       

然后使用ImmersionBar時候必須指定狀態(tài)欄顏色

       ZanImmersionBar.with(this)
            .statusBarColor(R.color.colorPrimary)
            .init();

注意:ZanImmersionBar一定要在設(shè)置完布局以后使用

③ 使用ZanImmersionBar的fitsSystemWindows(boolean fits)方法

        ZanImmersionBar.with(this)
            .fitsSystemWindows(true)  //使用該屬性,必須指定狀態(tài)欄顏色
            .statusBarColor(R.color.colorPrimary)
            .init();

④ 使用ZanImmersionBar的statusBarView(View view)方法

在標(biāo)題欄的上方增加View標(biāo)簽,高度指定為0dp

        
           
               
           
               
        

然后使用ZanImmersionBar的statusBarView方法,指定view就可以啦

         ZanImmersionBar.with(this)
               .statusBarView(view)
               .init();
         //或者
         //ZanImmersionBar.setStatusBarView(this,view);

⑤ 使用ZanImmersionBar的titleBar(View view)方法,原理是設(shè)置paddingTop

             ZanImmersionBar.with(this)
                   .titleBar(view) //可以為任意view,如果是自定義xml實(shí)現(xiàn)標(biāo)題欄的話,最外層節(jié)點(diǎn)不能為RelativeLayout
                   .init();
             //或者
             //ZanImmersionBar.setTitleBar(this, view);

⑥ 使用ZanImmersionBar的titleBarMarginTop(View view)方法,原理是設(shè)置marginTop

             ZanImmersionBar.with(this)
                   .titleBarMarginTop(view)  //可以為任意view
                   .statusBarColor(R.color.colorPrimary)  //指定狀態(tài)欄顏色,根據(jù)情況是否設(shè)置
                   .init();
             //或者使用靜態(tài)方法設(shè)置
             //ZanImmersionBar.setTitleBarMarginTop(this,view);
總結(jié)

在處理Android沉浸式狀態(tài)欄和導(dǎo)航欄開始會很頭大,并且會不理解相關(guān)設(shè)置的window的FLAG屬性,想要分清楚這些屬性的大意需要從出現(xiàn)背景出發(fā)拆封,先熟悉沉浸式出現(xiàn)的3個階段的屬性和版本能做什么和不能做什么,然后再去了解各個廠家定制化的屬性在哪些版本階段使用,以及是否需要對異形屏適配,最后才是在實(shí)際開發(fā)和需求中對狀態(tài)欄和導(dǎo)航欄處理。不過在Android6.0以后版本廠家的定制化狀態(tài)已經(jīng)越來越?jīng)]有意義了,以后Android原生趨勢也將會讓開發(fā)者使用沉浸式越來越舒服。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/76228.html

相關(guān)文章

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<