Android 修改状态栏属性

1、沉浸式状态栏

方法1、设置Theme 属性为透明状态栏
因为 API21 之后(也就是 android 5.0 之后)的状态栏,会默认覆盖一层半透明遮罩。且为了保持4.4以前系统正常使用,故需要三份 style 文件,即默认的values(不设置状态栏透明)、values-v19、values-v21(解决半透明遮罩问题)。

//valuse 
<style name="TranslucentTheme" parent="AppTheme"> </style> 
// values-v19。v19 开始有 android:windowTranslucentStatus 这个属性 
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar">
 <item name="android:windowTranslucentStatus">true</item>
</style> 
// values-v21。5.0 以上提供了 setStatusBarColor() 方法设置状态栏颜色。 
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> 
<item name="android:windowTranslucentStatus">false</item> 
<item name="android:windowTranslucentNavigation">true</item> 
<!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色--> 
<item name="android:statusBarColor">@android:color/transparent</item> 
</style>

但是我们经常会有这样的需求,有的界面需要使用状态栏,那么为了解决这个问题可以有一下方法

1、设置 fitsSystemWindows 属性
当该属性设置 true 时,会在屏幕最上方预留出状态栏高度的 padding;
在布局的最外层设置 android:fitsSystemWindows=”true” 属性。当然,也可以通过代码设置:

/** 
* 设置页面最外层布局 FitsSystemWindows 属性 
* @param activity * 
* @param value 
* */ 
 public static void setFitsSystemWindows(Activity activity, boolean value) 
   { 
     ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content);
     View parentView = contentFrameLayout.getChildAt(0);  
    if (parentView != null && Build.VERSION.SDK_INT >= 14)  
       { parentView.setFitsSystemWindows(value); }  
      }

通过该设置保留状态栏高度的 paddingTop 后,再设置状态栏的颜色。就可以达到设想的效果。但这种方式实现有些问题,例如我们想设置状态栏为蓝色,只能通过设置最外层布局的背景为蓝色来实现,然而一旦设置后,整个布局就都变成了蓝色,只能在下方的布局内容里另外再设置白色背景,而这样就存在过度绘制了。而且设置了 fitsSystemWindows=true 属性的页面,在点击 EditText 调出 软键盘时,整个视图都会被顶上去。

2、在布局中添加占位状态栏
一、可以在根布局文件中添加一个占位

<View 
  android:id="@+id/statusBarView" 
  android:background="@color/blue" 
  android:layout_width="match_parent"  
  android:layout_height="wrap_content"> 
 </View>

然后在代码中获取状态栏的高度,设置颜色并设置给占位状态栏

通过反射获取状态栏高度:

/**
* 利用反射获取状态栏高度
* @return
*/
public int getStatusBarHeight() {
  int result = 0;
  //获取状态栏高度的资源id
  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

设置占位视图高度

View statusBar = findViewById(R.id.statusBarView);
ViewGroup.LayoutParams layoutParams = statusBar.getLayoutParams();
layoutParams.height = getStatusBarHeight();

除了在布局中添加的这种方式外还可以在代码中添加,方便代码的封装

二、代码中添加占位状态栏

/** 
* 添加状态栏占位视图 * 
* @param activity 
* */
 private void addStatusViewWithColor(Activity activity, int color) 
 { 
    ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content); 
    View statusBarView = new View(activity);  
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,                   getStatusBarHeight(activity));  
    statusBarView.setBackgroundColor(color);  
    contentView.addView(statusBarView, lp); 
    }

3、在布局中添加PaddingTop 并且添加占位状态栏 (推荐)

手动给根视图设置一个 paddingTop ,高度为状态栏高度,相当于手动实现了 fitsSystemWindows=true 的效果,然后再在根视图加入一个占位视图,其高度也设置为状态栏高度。

//设置 paddingTop
ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    //5.0 以上直接设置状态栏颜色
    activity.getWindow().setStatusBarColor(color);
} else {
    //根布局添加占位状态栏
    ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView();
    View statusBarView = new View(activity);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            getStatusBarHeight(activity));
    statusBarView.setBackgroundColor(color);
    decorView.addView(statusBarView, lp);
}

方法2、通过代码设置主题修改

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
{ 
  int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 
  int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; 
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
   {
      Window window = getWindow();
      WindowManager.LayoutParams attributes = window.getAttributes(); 
      attributes.flags |= flagTranslucentNavigation; 
      window.setAttributes(attributes); 
      getWindow().setStatusBarColor(Color.TRANSPARENT); 
} else {
 Window window = getWindow(); 
 WindowManager.LayoutParams attributes = window.getAttributes(); 
 attributes.flags |= flagTranslucentStatus | flagTranslucentNavigation;   
  window.setAttributes(attributes); } }

但是从图片中也看到了,该方案会导致一个问题就是导航栏颜色变灰。
经测试,在 5.x 以下导航栏透明是可以生效的,但 5.x 以上导航栏会变灰色(正常情况下我们期望导航栏保持默认颜色黑色不变),但因为设置了FLAG_TRANSLUCENT_NAVIGATION,所以即使代码中设置 getWindow().setNavigationBarColor(Color.BLACK); 也是不起作用的。但如果不设置该 FLAG ,状态栏又无法被置为隐藏和设置透明。

2、设置状态栏字体颜色

很多国内三方Android系统都有深色状态栏字体模式,但是目前只看到了小米和魅族公开了各自的实现方法,支持底层Android4.4以上的版本。而Android官方在6.0版本才有了深色状态栏字体API。所以Android4.4以上系统版本可以修改状态栏颜色,但是只有小米的MIUI、魅族的Flyme和Android6.0以上系统可以把状态栏文字和图标换成深色。

1、Android6.0 以上不包括小米魅族

//设置成白色的背景,字体颜色为黑色。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(getResources().getColor(android.R.color.white));
    window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

2、小米

//设置成白色的背景,字体颜色为黑色。
public static boolean setMiuiStatusBarDarkMode(Activity activity, boolean darkmode) {
    Class<? extends Window> clazz = activity.getWindow().getClass();
    try {
        int darkModeFlag = 0;
        Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
        Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
        darkModeFlag = field.getInt(layoutParams);
        Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
        extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

3、魅族

//设置成白色的背景,字体颜色为黑色。

public static boolean setMeizuStatusBarDarkIcon(Activity activity, boolean dark) {
    boolean result = false;
    if (activity != null) {
        try {
            WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
            Field darkFlag = WindowManager.LayoutParams.class
                    .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
            Field meizuFlags = WindowManager.LayoutParams.class
                    .getDeclaredField("meizuFlags");
            darkFlag.setAccessible(true);
            meizuFlags.setAccessible(true);
            int bit = darkFlag.getInt(null);
            int value = meizuFlags.getInt(lp);
            if (dark) {
                value |= bit;
            } else {
                value &= ~bit;
            }
            meizuFlags.setInt(lp, value);
            activity.getWindow().setAttributes(lp);
            result = true;
        } catch (Exception e) {
        }
    }
    return result;
}

官方还提供了6.0以上亮色状态栏模式

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            activity.getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
   }

或者在style上添加属性

<item name="android:windowLightStatusBar">true</item>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值