1. <div id="f8mbs"></div>
        您好,歡迎來到源碼搜藏網!分享精神,快樂你我!
        [加入VIP] 設為首頁 | 收藏本站 | 網站地圖 | Sitemap | TAG標簽
      2. 首 頁
      3. 在線工具
      4. jquery手冊
      5. 當前位置:首頁 > 安卓源碼 > 技術博客 >

        Android開發徹底搞定 Kitkat+沉浸式狀態欄效果

        時間:2019-02-14 12:04 來源:浜掕仈緗 作者:源碼搜藏 瀏覽:收藏 挑錯 推薦 打印

        首先,我要實現的最終效果是這樣的,即在Android4.4及以上版本系統上,統一顯示為如下效果: 所謂沉浸式狀態欄 這里所說的沉浸式狀態欄,就是指上面的效果,狀態欄和Toolbar的顏色保持一致,融為一體的效果。 版本差異及解決方法 本文所用的示例使用的style

        首先,我要實現的最終效果是這樣的,即在Android4.4及以上版本系統上,統一顯示為如下效果:

        所謂“沉浸式”狀態欄

        這里所說的沉浸式狀態欄,就是指上面的效果,狀態欄和Toolbar的顏色保持一致,融為一體的效果。

        版本差異及解決方法

        本文所用的示例使用的style風格是NoActionBar的,標題欄使用的是Toolbar控件,請知悉。

        Android4.4

        Android4.4以前的版本,狀態欄的顏色都是黑色的,而且無法修改;但一般APP的Toolbar都不會設置為黑色,于是,兩者
        有十分明顯的顏色區分,各自占有不同的區域,填充不同的顏色。簡單的說,Android4.4以前的版本是無法做到
        沉浸式的效果的(做系統開發的除外),所以如果想要統一風格的話,可以設置APP最小支持的版本為4.4,如果
        不行,就沒辦法了,只能4.4以前一個樣式,4.4及以后一個樣式。

        Android4.4開始,新增了設置狀態欄背景色透明的屬性,新增的屬性是這兩個:

        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 
        WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION

        這兩個屬性分別設置狀態欄和導航欄背景色為全透明。(這里只討論狀態欄,只設置上面一個屬性就行,導航欄的類似)
        實現方法很簡單,在Activity初始化時,調用以下代碼:

        // Translucent status bar
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }

        由于是代碼設置,所以無法通過xml預覽到想要的結果,一定要在4.4真機上運行才能看到效果。

        到這里可能存在兩個問題:

        1. Toolbar把狀態欄的空間占用了,擠到一起。
        
        2. 狀態欄和Toolbar并沒有完全融為一體,而是從上到下,由黑色漸變到Toolbar的顏色。

        第一個現象是必現的,解決方法是在Toolbar的布局文件里加上一個屬性:

        android:fitsSystemWindows="true"

        這個屬性必須加在Toolbar或者Toolbar的父控件上,也就是,如果Toolbar直接寫在Activity的布局文件里,則在Toolbar上
        加這個屬性,如果Toolbar是include到Activity的布局文件里,則可以加到Toolbar的父控件里;

        <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            tools:context="com.chengsy.immersive.MainActivity">
        
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorPrimary"
                android:fitsSystemWindows="true"
                app:title="@string/app_name"
                app:titleTextColor="#FFFFFF">
        
            </android.support.v7.widget.Toolbar>
        
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="Hello World!" />
        
        </LinearLayout>

        上面這種情況,如果寫到linearlayout中,就會出現問題,StatusBar的背景色跟整個窗口的背景色一樣(或者跟桌面顏色一樣),而不是和Toolbar的
        顏色一樣。效果如下:

        第二個現象根據不同的系統廠商,效果不一樣,也就是不同的手機廠商做的不一樣,沒辦法,但是不是太影響沉浸式的效果。
        效果如下:

        總結一下,4.4版本,需要設置兩個地方來實現沉浸式效果:

        • 設置狀態欄透明

        • 設置Toolbar的fitsSystemWindows屬性為true

        Android5.0

        先看看通過上面的設置,程序運行在Android5.0的設備上是什么效果:
        可能的效果也有兩個,一個是我們想要的效果,沉浸式,不再配圖了,另一個是這樣的:

        這種效果是狀態欄的顏色上面覆蓋了一層半透明的顏色,不是全透明。當然,原因你懂得,不同廠商系統設計師的idea是不一樣的,
        但是這里說一下,谷歌官方的Mertial Design的設計規范是如上圖所示,并不是沉浸式的效果,但國內的APP現在普遍比較
        喜歡沉浸式的效果。

        那么如果要統一5.0的效果跟4.4的效果保持一致,全部都是沉浸式該怎么辦???
        這么辦---
        首先,Android5.0開始,系統又新增了設置狀態欄顏色值的屬性和接口:

        WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS

        通過這個屬性來設置設置狀態欄的背景色,來實現兩者融為一體的效果,代碼實現如下:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                getWindow().setStatusBarColor(Color.TRANSPARENT);// SDK21
        }

        原理很簡單,首先要清空之前設置的FLAG_TRANSLUCENT_STATUS屬性,然后添加修改狀態欄背景色的屬性FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
        ,最后給狀態欄設置為全透明。

        這里有坑,有的5.x的設備,如果調用這句代碼
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        狀態欄會變黑色,這時候需要去掉這句。但是去掉這句代碼,在6.0+系統上半透明的狀態欄又出現了。所以處理方法是判斷如果是某種特殊的系統,
        不調用上述代碼。

        Android6.0

        對于Android6.0及以后的系統,對這方面的支持就已經很完善和統一了,通過4.4設置的FLAG_TRANSLUCENT_STATUS屬性和
        fitsSystemWindows屬性就可以達到想要的效果了,不需要做特殊處理,版本內暫時不存在機型之間的差異。

        但是6.0也不是完全沒新的東西(指的是狀態欄這一塊內容),6.0新增了設置狀態欄里內容色調的屬性和接口,通過設置如下屬性,可以把狀態欄的文字
        色調由亮色改為暗色,亮色是白色,暗色是黑色:

        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

        看名字感覺跟我的描素不一樣啊,其實,這個屬性是把狀態欄標記為亮色調,從而,系統會自動把狀態欄的文字內容變為
        暗色調,如果你的APP的Toolbar顏色是亮色的,再配上亮色的內容就會不明顯,上面的代碼可以解決這個問題,自動將
        狀態欄的內容改為暗色調。

        其他問題

        • 輸入框的兼容問題

        如果想要頁面底部的輸入框可以被鍵盤頂起來,并且不影響頁面的沉浸式效果,需要做兩點:

         - AndroidManifest.xml文件配置鍵盤屬性:android:windowSoftInputMode="adjustResize"
         - Activity頁面根布局設置 android:fitsSystemWindows="true" 屬性

        布局代碼如下:

         <?xml version="1.0" encoding="utf-8"?>
         <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:app="http://schemas.android.com/apk/res-auto"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:fitsSystemWindows="true"
             android:orientation="vertical"
             tools:context="com.chengsy.immersive.MainActivity">
         
             <android.support.v7.widget.Toolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:background="@color/colorPrimary"
                 android:fitsSystemWindows="true"
                 app:title="@string/app_name"
                 app:titleTextColor="#FFFFFF">
         
             </android.support.v7.widget.Toolbar>
         
             <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_below="@+id/toolbar"
                 android:gravity="bottom">
         
                 <EditText
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:text="Hello World!" />
             </LinearLayout>
         
         </RelativeLayout>

        通過上面的處理,狀態欄的顏色不對了,變成了白色或者桌面的背景色,問題又來了。解決方法的原理就是給狀態欄填充上顏色,
        但是,給狀態欄修改顏色的屬性和接口在5.0才出現,[4.4--5.0)版本的怎么辦?用SystemBarTintManager,Github上的開源庫,
        解決眼前的問題。使用很簡單,引用這個庫:

         compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'

        代碼中設置:

         private SystemBarTintManager tintManager;
         
         tintManager = new SystemBarTintManager(this);
         tintManager.setStatusBarTintColor(getResources().getColor(R.color.colorPrimary));
         tintManager.setStatusBarTintEnabled(true);
        • 其他第三方控件的兼容,如ActionMode等

        有用到這個的自己去查、去嘗試吧,這個控件好久不用了,也不知道什么效果,可以參考這篇文章里的解決方法:
        沉浸式狀態欄實現及遇到的坑

        • 系統廠商的兼容,如MIUI系統等

        這里也介紹了MIUI系統的適配問題,供參考:
        沉浸式狀態欄實現及遇到的坑

        總結

        由于Android系統的開放性,以及系統廠商的不統一,導致Android系統的適配成為了另程序員頭疼的一大問題,沉浸式的效果同樣
        不好做到完全統一樣式,只能盡力而為之。通過上面的操作,基本可以保證大多數機型和系統的沉浸式效果,但仍然有個別無法適配的
        系統或機型,這里也無法一一列舉所有的情形,需要程序員們有針對性的設計代碼,解決問題。

        這里給出自己總結的一個方法,可以在BaseActivity中調用:

        首先,Toolbar要設置fitsSystemWindows屬性,如果頁面包含EditText,需同時在頁面根布局添加fitsSystemWindows屬性;
        其次,引用SystemBarTintManager庫提供支持;
        最后,調用如下代碼:

        private SystemBarTintManager tintManager;
        protected void initWindow() {
            // 4.4及以上版本設置狀態欄透明
            Window window = getWindow();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                // Translucent status bar
                window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            }
        
            // 解決4.4-5.0版本之間,頁面包含EditText無法適配的問題
            {
                // create our manager instance after the content view is set
                mTintManager = new SystemBarTintManager(this);
                // enable status bar tint
                mTintManager.setStatusBarTintEnabled(true);
                // enable navigation bar tint
                mTintManager.setNavigationBarTintEnabled(true);
        
                // 自定義狀態欄的顏色
                mTintManager.setStatusBarTintColor(getResources().getColor(R.color.colorPrimary));
            }
        
            // 解決[5.0-5.1.1]版本狀態欄沒有全透明的系統適配問題
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // 解決部分5.x系統使用狀態欄透明屬性后狀態欄變黑色,不使用這句代碼,在6.0設備上又出現半透明狀態欄
                // 需要特殊處理
                window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                
                window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.TRANSPARENT);
            }
            
            // 把狀態欄標記為淺色,然后狀態欄的字體顏色自動轉換為深色。
            // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            //     getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            // }
        Android開發徹底搞定 Kitkat+沉浸式狀態欄效果轉載http://www.rhcg.tw/appboke/39529.html
        標簽:網站源碼
        辽宁十一选五单双