轻松实现状态栏颜色变化
Posted 火龙裸先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了轻松实现状态栏颜色变化相关的知识,希望对你有一定的参考价值。
忙太长一段时间了,回过头来想想,还是不敢放松自己,今天就算熬夜也要坚持把这篇文章写完。为了自己以后方便,在各种地方都要用到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",如果不调用这个方法,就会导致布局中的内容覆盖到状态栏和导航栏上面了。
暂时就先写到这里吧,后续继续学习,一步步提高,程序员的生涯,无底洞!
以上是关于轻松实现状态栏颜色变化的主要内容,如果未能解决你的问题,请参考以下文章