Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 實現Android K的偽沉浸式

實現Android K的偽沉浸式

編輯:Android開發實例

       在Android 5.0之後引入了MD風格,從而狀態欄沉浸也成為了一種設計習慣。而停留在之Android L之前的Android系統則不能直接實現沉浸式,這裡就介紹一下如何實現Android K系列的偽沉浸式。

       關於沉浸式效果,這裡隨便貼幾張圖吧

 實現Android K的偽沉浸式

 Android L效果圖

 實現Android K的偽沉浸式

Android 4.2效果圖

       可以看出在Android K系列中,狀態欄是漸變的效果

       下面開始講解如何實現上圖的效果,在此就不贅述Android L或以上的沉浸式的效果實現了,在xml上配置幾個屬性就可以了。

       題外話:這篇文章介紹的都是使用Android Studio作為IDE開發Android的,如果使用的是其他IDE應按照相關設置進行設置或者配置xml等文件。

       開始學習偽沉浸式

       所謂的其他知識,就是創建一個其他App中的Activity共有的基類BaseActivity,讓其繼承AppCompatActivity,然後在基類中實現偽沉浸式,這樣Acticity就能專注於自己的內容,而把這些共有的設置交給BaseActivity處理。

       現在看看這部分如何處理,先看代碼:

Java代碼
  1. public class  BaseActivity extends AppCompatActivity {  
  2.   
  3.     private int mColor = -1;  
  4.       
  5.     public BaseActivity(){  
  6.     }  
  7.   
  8.     public BaseActivity(int color){  
  9.         super();  
  10.         mColor = color;  
  11.     }  
  12.   
  13.     @Override  
  14.     protected void onCreate(@Nullable Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState );  
  16.         StatusBarCompat.compat(this, ContextCompat.getColor(this, mColor));  
  17.     }  
  18.   
  19.     public static class StatusBarCompat{  
  20.   
  21.         private static final int INVALID_VAL = -1;  
  22.         private static final int COLOR_DEFAULT = Color.parseColor("#20000000");  
  23.   
  24.         public static  void compat(Activity activity, int statusColor){  
  25.             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){  
  26.                 if(statusColor != INVALID_VAL){  
  27.                     activity.getWindow().setStatusBarColor(statusColor);  
  28.                 }  
  29.                 return;  
  30.             }  
  31.   
  32.             if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT  
  33.                     && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){  
  34.                 int color = COLOR_DEFAULT;  
  35.                 ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);  
  36.   
  37.                 if(statusColor != INVALID_VAL){  
  38.                     color = statusColor;  
  39.                 }  
  40.   
  41.                 View statusBarView = new View(activity);  
  42.                 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,  
  43.                         getStatusBarHeight(activity));  
  44.                 statusBarView.setBackgroundColor(color);  
  45.   
  46.                 contentView.addView(statusBarView, lp);  
  47.                 //contentView.addView(statusBarView, 0, lp);  
  48.             }  
  49.         }  
  50.   
  51.         public static void compat(Activity activity){  
  52.             compat(activity, INVALID_VAL);  
  53.         }  
  54.   
  55.         public static int getStatusBarHeight(Context context){  
  56.             int result = 0;  
  57.   
  58.             int resourceId = context.getResources().getIdentifier("status_bar_height",  
  59.                     "dimen", "android");  
  60.   
  61.             if(resourceId > 0){  
  62.                 result = context.getResources().getDimensionPixelSize(resourceId);  
  63.             }  
  64.   
  65.             return result;  
  66.         }  
  67.     }  
  68. }  

       跟著步驟,沒必要全部看那些凌亂的代碼,在這裡講解重點部分,在BaseActivity中提供了一個單一參數的構造函數,目的是讓子類選擇偽沉浸的顏色,在onCreate函數中調用了StatusBarCompat.compat(this, ContextCompat.getColor(this, mColor))函數,StatusBarCompat是其內部類,我們看看compat函數是如何實現偽沉浸的。

       第一個if是判斷系統如果為Android L或以上的系統則直接調用setStatusBarColor函數,這是API 21之後提供設置狀態欄顏色的函數,然後是第三個if用於判斷是否為Android K系統,如果是則開始我們的步驟。裡面的內容其實是這樣的,我們在XML裡配置好狀態欄的背景為透明,然後在我們的布局中插入一個和狀態欄等高的View,從而在視覺上看起來就是沉浸式的效果了。從字面上很容易理解這樣做的意義,然後簡單分析一下可行性。首先,如何獲取我們的布局,方法很多,可以給根布局設置一個id,然後Activity.findViewById直接獲取根布局。其實在這裡也可以不獲取布局,可以在xml中設置一個View,然後在這裡獲取這個View並且設置它的高度為狀態欄的高度,背景為Activity中傳過來的顏色即可。這裡就不介紹這兩種方法,介紹一種獲取我們根布局的其他方法。代碼35行findViewById(android.R.id.content)獲取了一個FrameLayout,然後奇怪了,為什麼是獲取一個FrameLayout呢,其實是這樣的,我們的布局都是設置在AppCompatActivity的FrameLayout布局中的,這段代碼就是為了獲取這個ViewGroup的內容的,因此,現在我們手中就掌握了整個Activity的ViewGroup,我們的操作就在這裡進行。獲取了真正的根布局,當然是開始創建一個View,然後讓其高度和狀態欄高度一致,然後再設置到剛剛獲取的ViewGroup中去就可以了。其中getStatusBarHeight就是獲取系統狀態欄高度的函數,然後設置View的背景色,然後add到ViewGroup就完成了整個操作。現在工作還沒完成呢,既然是Android K的機子,先配置XML吧,在res目錄下新建一個values-v19的文件夾,然後新建styles.xml文件,貼上以下代碼:

XML/HTML代碼
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <style name="AppTheme" parent="@style/BaseAppTheme">  
  4.         <item name="android:windowTranslucentStatus">true</item>  
  5.     </style>  
  6. </resources>  

       順便看看BaseAppTheme的代碼,這部分代碼在res/values/styles裡面:

XML/HTML代碼
  1. <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar">  
  2.         <!-- Customize your theme here. -->  
  3.         <item name="colorPrimary">@color/colorPrimary</item>  
  4.         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>  
  5.         <item name="colorAccent">@color/colorAccent</item>  
  6. </style>  

      其中android:windowTranslucentStatus屬性設置的是狀態欄是否設置為透明狀態,這個是v19之後才引入的屬性。

      到這裡,看似好像完成了,但問題還沒完全解決,那就是ToolBar的空間位置問題,假如不處理,如圖:

 實現Android K的偽沉浸式

       看出效果是ToolBar和狀態欄擠成了一塊,但這不是這篇文章中所想要的效果,那應該怎麼辦呢?其實只需設置ToolBar的一個屬性android:fitsSystemWindows="true"即可。該屬性的意義就是讓當前設置這個屬性的view設置對應的padding為狀態欄騰出對應的空間,說白了就好像是paddingTop=statusBarHeight。

       按步驟設置好之後,還有一步,不然看到的是代碼裡面默認設置的顏色,所以要在Activity中傳遞color給BaseActivity,簡單的代碼如下:

Java代碼
  1. public MainActivity(){  
  2.     this(R.color.colorPrimary);  
  3. }  
  4.   
  5. private MainActivity(int color){  
  6.     super(color);  
  7. }  

       只需修改R.color.colorPrimary為自己需要的顏色即可。為什麼需要這樣操作,很簡單,因為默認啟動調用的是無參構造函數,所以讓無參去調用有參構造,即可實現,這也解釋了為什麼父類要去定義這個有參構造了。

       運行了一下效果,嗯,還不錯,但當你如果用的是這個方法添加的view作狀態欄背景色的話,其實有一個坑,不過我貼的代碼上已經解釋了這個坑的處理方法了。這個坑其實就是和DrawerLayout配合使用的時候,當你打開抽屜的時候,會看到側滑菜單在狀態欄的下面,如圖所示:

 實現Android K的偽沉浸式

       可以看到,狀態欄把側滑菜單擋住了,說白了其實是我們添加的view把狀態欄擋住了。如何解決呢,在上面代碼中注釋了一句,其實使用下面那個三參數的函數就可以解決這個問題了,如圖:

 實現Android K的偽沉浸式

       可以看出,側滑菜單已經覆蓋在充當狀態欄背景的那個view上面了。為什麼會這樣呢,理由很簡單,使用第一個函數的時候它是直接add到FrameLayout最上面的,所以就擋在了我們的布局上面,而addView(statusBar, 0, lp)的意思則是插入到第1個View的位置,因此就會讓它插入到我們的布局下面,因此就實現了我們所想要的效果。既然兩個參數有先後問題,那我們是否可以在Activity的onCreat函數中這樣操作呢,比如先super.onCreat然後再調用setContentView,看似這樣子我們的布局就應該在充當狀態欄背景的view上面了,其實這是一個坑,我們在onCreat中必須是先調用setContentView然後再調用基類的onCreat,否則,狀態欄的效果如圖:

 實現Android K的偽沉浸式

       其實,從setContentView的名字可以看出來為什麼了,既然這個是設置自定義布局,顯然,調用這個函數的時候會將FrameLayout裡面的內容清空,因此後調用這個函數的時候,之前add進去的view已經被清空了。

       到這裡,關於Android K的偽沉浸式效果就實現了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved