忙太長一段時間了,回過頭來想想,還是不敢放松自己,今天就算熬夜也要堅持把這篇文章寫完。為了自己以后方便,在各種地方都要用到toolbar或者其他的自定義頂部欄、亦或是ActionBar。
在這里,已經整理了一個工具類,以后想怎么用就怎么用了。
第一種效果:
這里,狀態欄顏色一致,其實狀態欄這時候是設置了50的透明值的。看看布局代碼:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout 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" tools:context="huolongluo.statusbarsample.MainActivity"> <include layout="@layout/toolbar" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
第一層用的ConstraintLayout,當然你也可以用別的,然后頂部是引用的一個ToolBar,如下:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </android.support.design.widget.AppBarLayout>
ToolBar第一層用的AppBarLayout,用這個的話,必須要先引入design包,看布局包名也很明確了。還有一點,大家都知道,要使用ToolBar的話,必須要設置APP主題為NoActionBar:
要實現上面的效果,六句代碼,當然,要是使用一些別的框架結合的話,能更精簡。代碼如下:
第二種效果:
這就是很多人說的沉浸式。布局代碼就是一個ImageView:
然后java類三句代碼實現:
第三種效果(遮蓋狀態欄):
這個效果呢,布局文件和第二種一模一樣,然后看看java是怎么實現的吧,原來如此簡單~~:
一句給控件設置圖片的代碼,另加重寫onWindowFocusChanged方法,搞定!
看完這些,假如還需要別的效果其實也可以去做,程序員的生活就是這樣,需要自己一步步提高,舉一反三。OK,以上效果的實現呢,最最核心的東西來了---實現工具類(StatusBarUtils.java):
1 package huolongluo.statusbarsample; 2 3 import android.annotation.TargetApi; 4 import android.app.Activity; 5 import android.content.Context; 6 import android.graphics.Color; 7 import android.os.Build; 8 import android.support.annotation.ColorInt; 9 import android.util.DisplayMetrics; 10 import android.view.Display; 11 import android.view.Gravity; 12 import android.view.View; 13 import android.view.ViewGroup; 14 import android.view.Window; 15 import android.view.WindowManager; 16 import android.widget.FrameLayout; 17 18 /** 19 * <p> 20 * Created by 火龍裸先生 on 2017/8/24 0024. 21 */ 22 23 public class StatusBarUtils { 24 25 private Activity activity; 26 27 public StatusBarUtils(Activity activity) { 28 this.activity = activity; 29 } 30 31 @TargetApi(Build.VERSION_CODES.KITKAT) 32 public void setColorBar(@ColorInt int color, int alpha) { 33 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 34 Window window = activity.getWindow(); 35 window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 36 window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 37 window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 38 int alphaColor = alpha == 0 ? color : calculateColor(color, alpha); 39 window.setStatusBarColor(alphaColor); 40 window.setNavigationBarColor(alphaColor); 41 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 42 Window window = activity.getWindow(); 43 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 44 int alphaColor = alpha == 0 ? color : calculateColor(color, alpha); 45 ViewGroup decorView = (ViewGroup) window.getDecorView(); 46 decorView.addView(createStatusBarView(activity, alphaColor)); 47 if (navigationBarExist(activity)) { 48 decorView.addView(createNavBarView(activity, alphaColor)); 49 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 50 } 51 setRootView(activity, true); 52 } 53 } 54 55 56 @TargetApi(Build.VERSION_CODES.KITKAT) 57 public void setColorBar(@ColorInt int color) { 58 setColorBar(color, 0); 59 } 60 61 62 @TargetApi(Build.VERSION_CODES.KITKAT) 63 public void setColorBarForDrawer(@ColorInt int color, int alpha) { 64 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 65 Window window = activity.getWindow(); 66 ViewGroup decorView = (ViewGroup) window.getDecorView(); 67 int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 68 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 69 if (navigationBarExist(activity)) { 70 option = option | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 71 } 72 decorView.setSystemUiVisibility(option); 73 window.setNavigationBarColor(Color.TRANSPARENT); 74 window.setStatusBarColor(Color.TRANSPARENT); 75 int alphaColor = alpha == 0 ? color : calculateColor(color, alpha); 76 decorView.addView(createStatusBarView(activity, alphaColor), 0); 77 if (navigationBarExist(activity)) { 78 decorView.addView(createNavBarView(activity, alphaColor), 1); 79 } 80 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 81 Window window = activity.getWindow(); 82 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 83 ViewGroup decorView = (ViewGroup) window.getDecorView(); 84 int alphaColor = alpha == 0 ? color : calculateColor(color, alpha); 85 decorView.addView(createStatusBarView(activity, alphaColor), 0); 86 if (navigationBarExist(activity)) { 87 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 88 decorView.addView(createNavBarView(activity, alphaColor), 1); 89 } 90 } 91 } 92 93 94 @TargetApi(Build.VERSION_CODES.KITKAT) 95 public void setColorBarForDrawer(@ColorInt int color) { 96 setColorBarForDrawer(color, 0); 97 } 98 99 100 @TargetApi(Build.VERSION_CODES.KITKAT) 101 public void setTransparentBar(@ColorInt int color, int alpha) { 102 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 103 Window window = activity.getWindow(); 104 View decorView = window.getDecorView(); 105 int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 106 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 107 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 108 decorView.setSystemUiVisibility(option); 109 110 int finalColor = alpha == 0 ? Color.TRANSPARENT : 111 Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 112 113 window.setNavigationBarColor(finalColor); 114 window.setStatusBarColor(finalColor); 115 116 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 117 Window window = activity.getWindow(); 118 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 119 ViewGroup decorView = (ViewGroup) window.getDecorView(); 120 int finalColor = alpha == 0 ? Color.TRANSPARENT : 121 Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 122 decorView.addView(createStatusBarView(activity, finalColor)); 123 if (navigationBarExist(activity)) { 124 window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 125 decorView.addView(createNavBarView(activity, finalColor)); 126 } 127 } 128 129 } 130 131 132 @TargetApi(Build.VERSION_CODES.KITKAT) 133 public void setImmersionBar() { 134 setTransparentBar(Color.TRANSPARENT, 0); 135 } 136 137 138 @TargetApi(Build.VERSION_CODES.KITKAT) 139 public void setHintBar() { 140 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 141 View decorView = activity.getWindow().getDecorView(); 142 decorView.setSystemUiVisibility( 143 View.SYSTEM_UI_FLAG_LAYOUT_STABLE 144 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 145 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 146 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 147 | View.SYSTEM_UI_FLAG_FULLSCREEN 148 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); 149 } 150 } 151 152 153 private View createStatusBarView(Context context, @ColorInt int color) { 154 View mStatusBarTintView = new View(context); 155 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams 156 (FrameLayout.LayoutParams.MATCH_PARENT, getStatusBarHeight(context)); 157 params.gravity = Gravity.TOP; 158 mStatusBarTintView.setLayoutParams(params); 159 mStatusBarTintView.setBackgroundColor(color); 160 return mStatusBarTintView; 161 } 162 163 private View createNavBarView(Context context, @ColorInt int color) { 164 View mNavBarTintView = new View(context); 165 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams 166 (FrameLayout.LayoutParams.MATCH_PARENT, getNavigationHeight(context)); 167 params.gravity = Gravity.BOTTOM; 168 mNavBarTintView.setLayoutParams(params); 169 mNavBarTintView.setBackgroundColor(color); 170 return mNavBarTintView; 171 } 172 173 174 private boolean navigationBarExist(Activity activity) { 175 WindowManager windowManager = activity.getWindowManager(); 176 Display d = windowManager.getDefaultDisplay(); 177 178 DisplayMetrics realDisplayMetrics = new DisplayMetrics(); 179 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 180 d.getRealMetrics(realDisplayMetrics); 181 } 182 183 int realHeight = realDisplayMetrics.heightPixels; 184 int realWidth = realDisplayMetrics.widthPixels; 185 186 DisplayMetrics displayMetrics = new DisplayMetrics(); 187 d.getMetrics(displayMetrics); 188 189 int displayHeight = displayMetrics.heightPixels; 190 int displayWidth = displayMetrics.widthPixels; 191 192 return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0; 193 } 194 195 196 @ColorInt 197 private int calculateColor(@ColorInt int color, int alpha) { 198 float a = 1 - alpha / 255f; 199 int red = color >> 16 & 0xff; 200 int green = color >> 8 & 0xff; 201 int blue = color & 0xff; 202 red = (int) (red * a + 0.5); 203 green = (int) (green * a + 0.5); 204 blue = (int) (blue * a + 0.5); 205 return 0xff << 24 | red << 16 | green << 8 | blue; 206 } 207 208 209 private void setRootView(Activity activity, boolean fit) { 210 ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); 211 for (int i = 0, count = parent.getChildCount(); i < count; i++) { 212 View childView = parent.getChildAt(i); 213 if (childView instanceof ViewGroup) { 214 childView.setFitsSystemWindows(fit); 215 ((ViewGroup) childView).setClipToPadding(fit); 216 } 217 } 218 } 219 220 221 private int getStatusBarHeight(Context context) { 222 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); 223 return context.getResources().getDimensionPixelSize(resourceId); 224 } 225 226 227 public int getNavigationHeight(Context context) { 228 229 int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); 230 return context.getResources().getDimensionPixelSize(resourceId); 231 } 232 }
要設置自定義顏色的狀態欄和導航欄只需要在 onCreate 方法中調用“setColorBar”方法,我們可以看到第一個方法里面傳入了兩個參數,第一個參數是自定義的顏色值,第二個參數是顏色深度值,最小為 0,最大為 255,當深度值為 0 時,狀態欄和導航欄的顏色就是第一個參數傳入的顏色值,即為第二個方法中的情況;當深度值不為 0 時,會根據深度值計算得到最終的顏色值,然后設置到狀態欄和導航欄上面。
正如大家所說,這里分別針對 Android 4.4 和 Android 5.0 以上做了不同處理,首先來看 Android 5.0 以上的情況,事實上 Android 5.0 以上的實現非常簡單,因為 Android 5.0 以上可以直接設置狀態欄和導航欄的顏色,所以只需要先得到最終的顏色值,然后調用 setStatusBarColor 和 setNavigationBarColor 方法進行設置就好了。然后 Android 4.4 稍微麻煩一點,首先必須要添加 FLAG_TRANSLUCENT_STATUS 這個 flag 來把狀態欄設置為透明,然后再在狀態欄上面添加一個 view 來保證狀態欄的顏色,然后再調用 navigationBarExist 方法來判斷當前手機是否存在導航欄,如果存在,對導航欄做同樣的處理,最后必須調用 setRootView 方法,其實這個方法是用來設置布局的子 view 的 fitsSystemWindows 參數的,相當於在布局中添加 android:fitsSystemWindows="true",如果不調用這個方法,就會導致布局中的內容覆蓋到狀態欄和導航欄上面了。
暫時就先寫到這里吧,后續繼續學習,一步步提高,程序員的生涯,無底洞!