編輯:關於android開發
在Android 5.0之後引入了MD風格,並且狀態欄沉浸也成為了一種設計習慣。而停留在之Android L之前的Android系統則不能直接實現沉浸式,這裡就介紹一下如何實現Android K系列的假裝沉浸式。
關於沉浸式效果,這裡隨便貼幾張圖吧
Android L效果圖
Android 4.2效果圖
可以看出在Android K系列中,狀態欄是漸變的效果
下面開始講解如何實現上圖的效果,在此就不贅述Android L或以上的沉浸式的效果實現了,在xml上配置幾個屬性就可以了
題外話:這篇文章介紹的都是使用Android Studio作為IDE開發Android的,如果使用的是其他IDE應按照相關設置進行設置或者配置xml等文件。
開始學習假裝沉浸式
所謂的其他知識,就是創建一個其他App中的Activity共有的基類BaseActivity,讓其繼承AppCompatActivity,然後在基類中實現假裝沉浸式,這樣Acticity就能專注於自己的內容,而把這些共有的設置交給BaseActivity處理。
現在看看這部分如何處理,先看代碼:
1 public class BaseActivity extends AppCompatActivity { 2 3 private int mColor; 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文件,貼上以下代碼:
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裡面:
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的空間位置問題,假如不處理,如圖:
看出效果是ToolBar和狀態欄擠成了一塊,但這不是這篇文章中所想要的效果,那應該怎麼辦呢?其實只需設置ToolBar的一個屬性android:fitsSystemWindows="true"即可。該屬性的意義就是讓當前設置這個屬性的view設置對應的padding為狀態欄騰出對應的空間,說白了就好像是paddingTop=statusHeight。
按步驟設置好之後,還有一步,不然看到的是代碼裡面默認設置的顏色,所以要在Activity中傳遞color給BaseActivity,簡單的代碼如下:
1 public MainActivity(){ 2 this(R.color.colorPrimary); 3 } 4 5 private MainActivity(int color){ 6 super(color); 7 }
只需修改R.color.colorPrimary為自己需要的顏色即可。為什麼需要這樣操作,很簡單,因為默認啟動調用的是無參構造函數,所以讓無參去調用有參構造,即可實現,這也解釋了為什麼父類要去定義這個有參構造了。
運行了一下效果,嗯,還不錯,但當你如果用的是這個方法添加的view作狀態欄背景色的話,其實有一個坑,不過我貼的代碼上已經解釋了這個坑的處理方法了。這個坑其實就是和DrawerLayout配合使用的時候,當你打開抽屜的時候,會看到側滑菜單在狀態欄的下面,如圖所示:
可以看到,狀態欄把側滑菜單擋住了,說白了其實是我們添加的view把狀態欄擋住了。如何解決呢,在上面代碼中注釋了一句,其實使用下面那個三參數的函數就可以解決這個問題了,如圖:
可以看出,側滑菜單已經覆蓋在假裝狀態欄的那個view上面了。為什麼會這樣呢,理由很簡單,使用第一個函數的時候它是直接add到FrameLayout最上面的,所以就擋在了我們的布局上面,而addView(statusBar, 0, lp)的意思則是插入到第1個View的位置,因此就會讓它插入到我們的布局下面,因此就實現了我們所想要的效果。既然兩個參數有先後問題,那我們是否可以在Activity的onCreat函數中這樣操作呢,比如先super.onCreat然後再調用setContentView,看似這樣子我們的布局就應該在假裝狀態欄背景的view上面了,其實這是一個坑,我們在onCreat中必須是先調用setContentView然後再調用基類的onCreat,否則,狀態欄的效果如圖:
其實,從setContentView的名字可以看出來為什麼了,既然這個是設置自定義布局,顯然,調用這個函數的時候會將FrameLayout裡面的內容清空,因此後調用這個函數的時候,之前add
進去的view已經被清空了。
到這裡,關於Android K的假裝沉浸式效果就實現了。
Android深度探索與HAL驅動開發(卷1)-- 第七章隨筆,android驅動開發應用程序、庫、內核、驅動程序的關系 從上到下,一個軟件系統可以分為
插入排序和希爾排序插入排序:插入排序由n-1趟排序組成。第 i 趟排序前,保證從位置 0 到位置i-1 上的元素已經是排序狀態(這是插入排序正確的原因,也是前提條件)。所
初識genymotion安裝遇上的VirtualBox問題,genymotionvirtualbox 想必做過Android開發的
如何用Sencha Touch打包Android的APK 什麼是Sencha Touch 前不久基於JavaScript編寫的Ajax框架ExtJS,將現有的ExtJ