zoukankan      html  css  js  c++  java
  • 另外一种设置沉浸式标题栏的方式

    今天又看到了另外一种设置沉浸式标题栏的方式,比上次写的那个使用主题,设置主题背景色的要好很多了。尤其是设置主题背景色后,程序从后台到前台ui界面没加载出来会显示出短暂的标题栏的颜色,因此设置主题背景颜色的方式还是有些缺陷。

    废话不多说,我介绍的这个方法使用了小米的一个类:SystemBarTintManager

    小米官网的地址 http://dev.xiaomi.com/doc/p=4769/index.html

    经过测试在其他的手机上一样适用,只是那个设置标题栏字体颜色为黑色不能用而已。

      1 /*
      2  * Copyright (C) 2013 readyState Software Ltd
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.readystatesoftware.systembartint;
     18 
     19 import java.lang.reflect.Field;
     20 import java.lang.reflect.Method;
     21 
     22 import android.annotation.SuppressLint;
     23 import android.annotation.TargetApi;
     24 import android.app.Activity;
     25 import android.content.Context;
     26 import android.content.res.Configuration;
     27 import android.content.res.Resources;
     28 import android.content.res.TypedArray;
     29 import android.graphics.drawable.Drawable;
     30 import android.os.Build;
     31 import android.util.DisplayMetrics;
     32 import android.util.TypedValue;
     33 import android.view.Gravity;
     34 import android.view.View;
     35 import android.view.ViewConfiguration;
     36 import android.view.ViewGroup;
     37 import android.view.Window;
     38 import android.view.WindowManager;
     39 import android.widget.FrameLayout.LayoutParams;
     40 
     41 /**
     42  * Class to manage status and navigation bar tint effects when using KitKat
     43  * translucent system UI modes.
     44  *
     45  */
     46 public class SystemBarTintManager {
     47 
     48     /**
     49      * The default system bar tint color value.
     50      */
     51     public static final int DEFAULT_TINT_COLOR = 0x99000000;
     52 
     53     private final SystemBarConfig mConfig;
     54     private boolean mStatusBarAvailable;
     55     private boolean mNavBarAvailable;
     56     private boolean mStatusBarTintEnabled;
     57     private boolean mNavBarTintEnabled;
     58     private View mStatusBarTintView;
     59     private View mNavBarTintView;
     60     private static boolean sIsMiuiV6;
     61 
     62     static {
     63         try {
     64             Class<?> sysClass = Class.forName("android.os.SystemProperties");
     65             Method getStringMethod = sysClass.getDeclaredMethod("get", String.class);
     66             sIsMiuiV6 = "V6".equals((String) getStringMethod.invoke(sysClass, "ro.miui.ui.version.name"));
     67         } catch (Exception e) {
     68             e.printStackTrace();
     69         }
     70     }
     71 
     72     /**
     73      * Constructor. Call this in the host activity onCreate method after its
     74      * content view has been set. You should always create new instances when
     75      * the host activity is recreated.
     76      *
     77      * @param activity The host activity.
     78      */
     79     @TargetApi(19)
     80     public SystemBarTintManager(Activity activity) {
     81 
     82         Window win = activity.getWindow();
     83         ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
     84 
     85         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     86             // check theme attrs
     87             int[] attrs = {android.R.attr.windowTranslucentStatus,
     88                     android.R.attr.windowTranslucentNavigation};
     89             TypedArray a = activity.obtainStyledAttributes(attrs);
     90             try {
     91                 mStatusBarAvailable = a.getBoolean(0, false);
     92                 mNavBarAvailable = a.getBoolean(1, false);
     93             } finally {
     94                 a.recycle();
     95             }
     96 
     97             // check window flags
     98             WindowManager.LayoutParams winParams = win.getAttributes();
     99             int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
    100             if ((winParams.flags & bits) != 0) {
    101                 mStatusBarAvailable = true;
    102             }
    103             bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
    104             if ((winParams.flags & bits) != 0) {
    105                 mNavBarAvailable = true;
    106             }
    107         }
    108 
    109         mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
    110         // device might not have virtual navigation keys
    111         if (!mConfig.hasNavigtionBar()) {
    112             mNavBarAvailable = false;
    113         }
    114 
    115         if (mStatusBarAvailable) {
    116             setupStatusBarView(activity, decorViewGroup);
    117         }
    118         if (mNavBarAvailable) {
    119             setupNavBarView(activity, decorViewGroup);
    120         }
    121 
    122     }
    123 
    124     /**
    125      * Enable tinting of the system status bar.
    126      *
    127      * If the platform is running Jelly Bean or earlier, or translucent system
    128      * UI modes have not been enabled in either the theme or via window flags,
    129      * then this method does nothing.
    130      *
    131      * @param enabled True to enable tinting, false to disable it (default).
    132      */
    133     public void setStatusBarTintEnabled(boolean enabled) {
    134         mStatusBarTintEnabled = enabled;
    135         if (mStatusBarAvailable) {
    136             mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
    137         }
    138     }
    139 
    140     /**
    141      * set status bar darkmode
    142      * @param darkmode
    143      * @param activity
    144      */
    145     public void setStatusBarDarkMode(boolean darkmode, Activity activity) {
    146         if (sIsMiuiV6) {
    147             Class<? extends Window> clazz = activity.getWindow().getClass();
    148             try {
    149             int darkModeFlag = 0;
    150             Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
    151             Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
    152             darkModeFlag = field.getInt(layoutParams);
    153             Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
    154             extraFlagField.invoke(activity.getWindow(), darkmode ? darkModeFlag : 0, darkModeFlag);
    155             } catch (Exception e) {
    156                 e.printStackTrace();
    157             }
    158         }
    159     }
    160 
    161     /**
    162      * Enable tinting of the system navigation bar.
    163      *
    164      * If the platform does not have soft navigation keys, is running Jelly Bean
    165      * or earlier, or translucent system UI modes have not been enabled in either
    166      * the theme or via window flags, then this method does nothing.
    167      *
    168      * @param enabled True to enable tinting, false to disable it (default).
    169      */
    170     public void setNavigationBarTintEnabled(boolean enabled) {
    171         mNavBarTintEnabled = enabled;
    172         if (mNavBarAvailable) {
    173             mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
    174         }
    175     }
    176 
    177     /**
    178      * Apply the specified color tint to all system UI bars.
    179      *
    180      * @param color The color of the background tint.
    181      */
    182     public void setTintColor(int color) {
    183         setStatusBarTintColor(color);
    184         setNavigationBarTintColor(color);
    185     }
    186 
    187     /**
    188      * Apply the specified drawable or color resource to all system UI bars.
    189      *
    190      * @param res The identifier of the resource.
    191      */
    192     public void setTintResource(int res) {
    193         setStatusBarTintResource(res);
    194         setNavigationBarTintResource(res);
    195     }
    196 
    197     /**
    198      * Apply the specified drawable to all system UI bars.
    199      *
    200      * @param drawable The drawable to use as the background, or null to remove it.
    201      */
    202     public void setTintDrawable(Drawable drawable) {
    203         setStatusBarTintDrawable(drawable);
    204         setNavigationBarTintDrawable(drawable);
    205     }
    206 
    207     /**
    208      * Apply the specified alpha to all system UI bars.
    209      *
    210      * @param alpha The alpha to use
    211      */
    212     public void setTintAlpha(float alpha) {
    213         setStatusBarAlpha(alpha);
    214         setNavigationBarAlpha(alpha);
    215     }
    216 
    217     /**
    218      * Apply the specified color tint to the system status bar.
    219      *
    220      * @param color The color of the background tint.
    221      */
    222     public void setStatusBarTintColor(int color) {
    223         if (mStatusBarAvailable) {
    224             mStatusBarTintView.setBackgroundColor(color);
    225         }
    226     }
    227 
    228     /**
    229      * Apply the specified drawable or color resource to the system status bar.
    230      *
    231      * @param res The identifier of the resource.
    232      */
    233     public void setStatusBarTintResource(int res) {
    234         if (mStatusBarAvailable) {
    235             mStatusBarTintView.setBackgroundResource(res);
    236         }
    237     }
    238 
    239     /**
    240      * Apply the specified drawable to the system status bar.
    241      *
    242      * @param drawable The drawable to use as the background, or null to remove it.
    243      */
    244     @SuppressWarnings("deprecation")
    245     public void setStatusBarTintDrawable(Drawable drawable) {
    246         if (mStatusBarAvailable) {
    247             mStatusBarTintView.setBackgroundDrawable(drawable);
    248         }
    249     }
    250 
    251     /**
    252      * Apply the specified alpha to the system status bar.
    253      *
    254      * @param alpha The alpha to use
    255      */
    256     @TargetApi(11)
    257     public void setStatusBarAlpha(float alpha) {
    258         if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    259             mStatusBarTintView.setAlpha(alpha);
    260         }
    261     }
    262 
    263     /**
    264      * Apply the specified color tint to the system navigation bar.
    265      *
    266      * @param color The color of the background tint.
    267      */
    268     public void setNavigationBarTintColor(int color) {
    269         if (mNavBarAvailable) {
    270             mNavBarTintView.setBackgroundColor(color);
    271         }
    272     }
    273 
    274     /**
    275      * Apply the specified drawable or color resource to the system navigation bar.
    276      *
    277      * @param res The identifier of the resource.
    278      */
    279     public void setNavigationBarTintResource(int res) {
    280         if (mNavBarAvailable) {
    281             mNavBarTintView.setBackgroundResource(res);
    282         }
    283     }
    284 
    285     /**
    286      * Apply the specified drawable to the system navigation bar.
    287      *
    288      * @param drawable The drawable to use as the background, or null to remove it.
    289      */
    290     @SuppressWarnings("deprecation")
    291     public void setNavigationBarTintDrawable(Drawable drawable) {
    292         if (mNavBarAvailable) {
    293             mNavBarTintView.setBackgroundDrawable(drawable);
    294         }
    295     }
    296 
    297     /**
    298      * Apply the specified alpha to the system navigation bar.
    299      *
    300      * @param alpha The alpha to use
    301      */
    302     @TargetApi(11)
    303     public void setNavigationBarAlpha(float alpha) {
    304         if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    305             mNavBarTintView.setAlpha(alpha);
    306         }
    307     }
    308 
    309     /**
    310      * Get the system bar configuration.
    311      *
    312      * @return The system bar configuration for the current device configuration.
    313      */
    314     public SystemBarConfig getConfig() {
    315         return mConfig;
    316     }
    317 
    318     /**
    319      * Is tinting enabled for the system status bar?
    320      *
    321      * @return True if enabled, False otherwise.
    322      */
    323     public boolean isStatusBarTintEnabled() {
    324         return mStatusBarTintEnabled;
    325     }
    326 
    327     /**
    328      * Is tinting enabled for the system navigation bar?
    329      *
    330      * @return True if enabled, False otherwise.
    331      */
    332     public boolean isNavBarTintEnabled() {
    333         return mNavBarTintEnabled;
    334     }
    335 
    336     private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
    337         mStatusBarTintView = new View(context);
    338         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
    339         params.gravity = Gravity.TOP;
    340         if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
    341             params.rightMargin = mConfig.getNavigationBarWidth();
    342         }
    343         mStatusBarTintView.setLayoutParams(params);
    344         mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
    345         mStatusBarTintView.setVisibility(View.GONE);
    346         decorViewGroup.addView(mStatusBarTintView);
    347     }
    348 
    349     private void setupNavBarView(Context context, ViewGroup decorViewGroup) {
    350         mNavBarTintView = new View(context);
    351         LayoutParams params;
    352         if (mConfig.isNavigationAtBottom()) {
    353             params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
    354             params.gravity = Gravity.BOTTOM;
    355         } else {
    356             params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);
    357             params.gravity = Gravity.RIGHT;
    358         }
    359         mNavBarTintView.setLayoutParams(params);
    360         mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
    361         mNavBarTintView.setVisibility(View.GONE);
    362         decorViewGroup.addView(mNavBarTintView);
    363     }
    364 
    365     /**
    366      * Class which describes system bar sizing and other characteristics for the current
    367      * device configuration.
    368      *
    369      */
    370     public static class SystemBarConfig {
    371 
    372         private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
    373         private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
    374         private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
    375         private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
    376 
    377         private final boolean mTranslucentStatusBar;
    378         private final boolean mTranslucentNavBar;
    379         private final int mStatusBarHeight;
    380         private final int mActionBarHeight;
    381         private final boolean mHasNavigationBar;
    382         private final int mNavigationBarHeight;
    383         private final int mNavigationBarWidth;
    384         private final boolean mInPortrait;
    385         private final float mSmallestWidthDp;
    386 
    387         private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
    388             Resources res = activity.getResources();
    389             mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
    390             mSmallestWidthDp = getSmallestWidthDp(activity);
    391             mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
    392             mActionBarHeight = getActionBarHeight(activity);
    393             mNavigationBarHeight = getNavigationBarHeight(activity);
    394             mNavigationBarWidth = getNavigationBarWidth(activity);
    395             mHasNavigationBar = (mNavigationBarHeight > 0);
    396             mTranslucentStatusBar = translucentStatusBar;
    397             mTranslucentNavBar = traslucentNavBar;
    398         }
    399 
    400         @TargetApi(14)
    401         private int getActionBarHeight(Context context) {
    402             int result = 0;
    403             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    404                 TypedValue tv = new TypedValue();
    405                 context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
    406                 result = context.getResources().getDimensionPixelSize(tv.resourceId);
    407             }
    408             return result;
    409         }
    410 
    411         @TargetApi(14)
    412         private int getNavigationBarHeight(Context context) {
    413             Resources res = context.getResources();
    414             int result = 0;
    415             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    416                 if (!ViewConfiguration.get(context).hasPermanentMenuKey()) {
    417                     String key;
    418                     if (mInPortrait) {
    419                         key = NAV_BAR_HEIGHT_RES_NAME;
    420                     } else {
    421                         key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
    422                     }
    423                     return getInternalDimensionSize(res, key);
    424                 }
    425             }
    426             return result;
    427         }
    428 
    429         @TargetApi(14)
    430         private int getNavigationBarWidth(Context context) {
    431             Resources res = context.getResources();
    432             int result = 0;
    433             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    434                 if (!ViewConfiguration.get(context).hasPermanentMenuKey()) {
    435                     return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
    436                 }
    437             }
    438             return result;
    439         }
    440 
    441         private int getInternalDimensionSize(Resources res, String key) {
    442             int result = 0;
    443             int resourceId = res.getIdentifier(key, "dimen", "android");
    444             if (resourceId > 0) {
    445                 result = res.getDimensionPixelSize(resourceId);
    446             }
    447             return result;
    448         }
    449 
    450         @SuppressLint("NewApi")
    451         private float getSmallestWidthDp(Activity activity) {
    452             DisplayMetrics metrics = new DisplayMetrics();
    453             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    454                 activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
    455             } else {
    456                 // TODO this is not correct, but we don't really care pre-kitkat
    457                 activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
    458             }
    459             float widthDp = metrics.widthPixels / metrics.density;
    460             float heightDp = metrics.heightPixels / metrics.density;
    461             return Math.min(widthDp, heightDp);
    462         }
    463 
    464         /**
    465          * Should a navigation bar appear at the bottom of the screen in the current
    466          * device configuration? A navigation bar may appear on the right side of
    467          * the screen in certain configurations.
    468          *
    469          * @return True if navigation should appear at the bottom of the screen, False otherwise.
    470          */
    471         public boolean isNavigationAtBottom() {
    472             return (mSmallestWidthDp >= 600 || mInPortrait);
    473         }
    474 
    475         /**
    476          * Get the height of the system status bar.
    477          *
    478          * @return The height of the status bar (in pixels).
    479          */
    480         public int getStatusBarHeight() {
    481             return mStatusBarHeight;
    482         }
    483 
    484         /**
    485          * Get the height of the action bar.
    486          *
    487          * @return The height of the action bar (in pixels).
    488          */
    489         public int getActionBarHeight() {
    490             return mActionBarHeight;
    491         }
    492 
    493         /**
    494          * Does this device have a system navigation bar?
    495          *
    496          * @return True if this device uses soft key navigation, False otherwise.
    497          */
    498         public boolean hasNavigtionBar() {
    499             return mHasNavigationBar;
    500         }
    501 
    502         /**
    503          * Get the height of the system navigation bar.
    504          *
    505          * @return The height of the navigation bar (in pixels). If the device does not have
    506          * soft navigation keys, this will always return 0.
    507          */
    508         public int getNavigationBarHeight() {
    509             return mNavigationBarHeight;
    510         }
    511 
    512         /**
    513          * Get the width of the system navigation bar when it is placed vertically on the screen.
    514          *
    515          * @return The width of the navigation bar (in pixels). If the device does not have
    516          * soft navigation keys, this will always return 0.
    517          */
    518         public int getNavigationBarWidth() {
    519             return mNavigationBarWidth;
    520         }
    521 
    522         /**
    523          * Get the layout inset for any system UI that appears at the top of the screen.
    524          *
    525          * @param withActionBar True to include the height of the action bar, False otherwise.
    526          * @return The layout inset (in pixels).
    527          */
    528         public int getPixelInsetTop(boolean withActionBar) {
    529             return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
    530         }
    531 
    532         /**
    533          * Get the layout inset for any system UI that appears at the bottom of the screen.
    534          *
    535          * @return The layout inset (in pixels).
    536          */
    537         public int getPixelInsetBottom() {
    538             if (mTranslucentNavBar && isNavigationAtBottom()) {
    539                 return mNavigationBarHeight;
    540             } else {
    541                 return 0;
    542             }
    543         }
    544 
    545         /**
    546          * Get the layout inset for any system UI that appears at the right of the screen.
    547          *
    548          * @return The layout inset (in pixels).
    549          */
    550         public int getPixelInsetRight() {
    551             if (mTranslucentNavBar && !isNavigationAtBottom()) {
    552                 return mNavigationBarWidth;
    553             } else {
    554                 return 0;
    555             }
    556         }
    557 
    558     }
    559 
    560 }

    使用起来也很简单,在你的activity或者baseactivity的oncreate方法中加入以下代码:

    1 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    2             setTranslucentStatus(true);
    3         }
    4         mTintManager = new SystemBarTintManager(this);
    5         mTintManager.setStatusBarTintEnabled(true);
    6         //使StatusBarTintView 和 actionbar的颜色保持一致,风格统一。
    7         mTintManager.setStatusBarTintResource(R.color.navbar);
    8         // 设置状态栏的文字颜色
    9         mTintManager.setStatusBarDarkMode(false, this);

    setTranslucentStatus方法

     1 @TargetApi(19)
     2     protected void setTranslucentStatus(boolean on) {
     3         Window win = getWindow();
     4         WindowManager.LayoutParams winParams = win.getAttributes();
     5         final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
     6         if (on) {
     7             winParams.flags |= bits;
     8         } else {
     9             winParams.flags &= ~bits;
    10         }
    11         win.setAttributes(winParams);
    12     }

    然后需要在你的布局文件最外层添加以下代码

     1 android:fitsSystemWindows="true"

    2 android:clipToPadding="false" 这个在设置主题的那里是设置为true的,注意区分

    如果你只用了普通的activity,那么一切事情都已经结束了。但我做的司信项目,在主界面上用的是一个activitygroup,然后用tabhost添加了4个activity,这样的话会有一些出入,需要在activitygroup的方法上写上以上代码,activity继承了baseactivity,因此也加入了这些属性,会造成自定义的导航栏文字显示不全。

    这个时候就再调用一下

    mTintManager.setStatusBarTintEnabled(false);//把自定义的titlebar设置不显示

    这样就可以了,效果是与之前的一样的,因此不再贴图。好处就是不会忽然闪一下之前的红色背景了。
  • 相关阅读:
    实现货币金额中文大写转换的程序
    大数阶乘的计算(三)
    全国15亿人口中选1000个代表有多少种选法?
    DB Query Analyzer 中断SQL语句的执行
    Android_Preference存取数据
    Centos 学习笔记软件包管理
    Centos学习笔记文件搜索命令
    《计算机时代》2011年第12期刊登出《DB Query Analyzer中断SQL语句的执行》
    Centos学习笔记linux用户管理
    Centos学习笔记 linux 常用命令:压缩解压命令
  • 原文地址:https://www.cnblogs.com/dongweiq/p/4448074.html
Copyright © 2011-2022 走看看