zoukankan      html  css  js  c++  java
  • Android Immersive Mode (沉浸模式) 还是 Translucent Bars (透明状态栏)

    Immersive Mode (沉浸模式) 还是 Translucent Bars (透明状态栏)

    【科普】什么叫真正的“沉浸式”状态栏?

    为什么在国内会有很多用户把「透明栏」(Translucent Bars)称作 「沉浸式顶栏」?

    MIUI 6 沉浸式状态栏调用方法

    完全隐藏 System Bars 的 Immersive Mode, 在大部分时候 Translucent Bars 并不能营造沉浸式体验

    当Android系统版本大于19(4.4),就可以开启透明标题栏:

    可以将其封装成方法进行调用。

     1 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     2             Window win = getWindow();
     3 
     4             WindowManager.LayoutParams winParams = win.getAttributes();
     5             winParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
     6             win.setAttributes(winParams);
     7 
     8             SystemBarTintManager tintManager = new SystemBarTintManager(this);
     9             tintManager.setStatusBarTintEnabled(true);
    10             tintManager.setStatusBarTintColor(Color.TRANSPARENT);
    11         }

    注意:

    1. 单纯图片背景时,要使得视图xml根视图的,背景图全屏时,需要设置isFitsSystemWindows=false。

    2.对于有TopBar的,需要设置根视图的paddingTop:

     1 mRootView.setPadding(0, getStatusBarHeight(mContext), 0, 0);
     2 // 通过反射获取状态栏高度
     3 public static int getStatusBarHeight(Context context) {
     4         try {
     5             Class<?> c = Class.forName("com.android.internal.R$dimen");
     6             Object obj = c.newInstance();
     7             Field field = c.getField("status_bar_height");
     8             int x = Integer.parseInt(field.get(obj).toString());
     9 
    10             return context.getResources().getDimensionPixelSize(x);
    11         } catch (Exception e) {
    12             e.printStackTrace();
    13         }
    14 
    15         return 0;
    16     }

    // 沉浸式状态栏 

    Android UI ImmersiveMode沉浸模式

    Android 沉浸式状态栏

    其第三方源代码:

      1 /**
      2  * Class to manage status and navigation bar tint effects when using KitKat 
      3  * translucent system UI modes.
      4  *
      5  */
      6 public class SystemBarTintManager {
      7 
      8     static {
      9         // Android allows a system property to override the presence of the navigation bar.
     10         // Used by the emulator.
     11         // See https://github.com/android/platform_frameworks_base/blob/master/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java#L1076
     12         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     13             try {
     14                 Class c = Class.forName("android.os.SystemProperties");
     15                 Method m = c.getDeclaredMethod("get", String.class);
     16                 m.setAccessible(true);
     17                 sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
     18             } catch (Throwable e) {
     19                 sNavBarOverride = null;
     20             }
     21         }
     22     }
     23 
     24 
     25     /**
     26      * The default system bar tint color value.
     27      */
     28     public static final int DEFAULT_TINT_COLOR = 0x99000000;
     29 
     30     private static String sNavBarOverride;
     31 
     32     private final SystemBarConfig mConfig;
     33     private boolean mStatusBarAvailable;
     34     private boolean mNavBarAvailable;
     35     private boolean mStatusBarTintEnabled;
     36     private boolean mNavBarTintEnabled;
     37     private View mStatusBarTintView;
     38     private View mNavBarTintView;
     39 
     40     /**
     41      * Constructor. Call this in the host activity onCreate method after its
     42      * content view has been set. You should always create new instances when
     43      * the host activity is recreated.
     44      *
     45      * @param activity The host activity.
     46      */
     47     @TargetApi(19)
     48     public SystemBarTintManager(Activity activity) {
     49 
     50         Window win = activity.getWindow();
     51         ViewGroup decorViewGroup = (ViewGroup) win.getDecorView();
     52 
     53         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     54             // check theme attrs
     55             int[] attrs = {android.R.attr.windowTranslucentStatus,
     56                     android.R.attr.windowTranslucentNavigation};
     57             TypedArray a = activity.obtainStyledAttributes(attrs);
     58             try {
     59                 mStatusBarAvailable = a.getBoolean(0, false);
     60                 mNavBarAvailable = a.getBoolean(1, false);
     61             } finally {
     62                 a.recycle();
     63             }
     64 
     65             // check window flags
     66             WindowManager.LayoutParams winParams = win.getAttributes();
     67             int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
     68             if ((winParams.flags & bits) != 0) {
     69                 mStatusBarAvailable = true;
     70             }
     71             bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
     72             if ((winParams.flags & bits) != 0) {
     73                 mNavBarAvailable = true;
     74             }
     75         }
     76 
     77         mConfig = new SystemBarConfig(activity, mStatusBarAvailable, mNavBarAvailable);
     78         // device might not have virtual navigation keys
     79         if (!mConfig.hasNavigtionBar()) {
     80             mNavBarAvailable = false;
     81         }
     82 
     83         if (mStatusBarAvailable) {
     84             setupStatusBarView(activity, decorViewGroup);
     85         }
     86         if (mNavBarAvailable) {
     87             setupNavBarView(activity, decorViewGroup);
     88         }
     89 
     90     }
     91 
     92     /**
     93      * Enable tinting of the system status bar.
     94      *
     95      * If the platform is running Jelly Bean or earlier, or translucent system
     96      * UI modes have not been enabled in either the theme or via window flags,
     97      * then this method does nothing.
     98      *
     99      * @param enabled True to enable tinting, false to disable it (default).
    100      */
    101     public void setStatusBarTintEnabled(boolean enabled) {
    102         mStatusBarTintEnabled = enabled;
    103         if (mStatusBarAvailable) {
    104             mStatusBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
    105         }
    106     }
    107 
    108     /**
    109      * Enable tinting of the system navigation bar.
    110      *
    111      * If the platform does not have soft navigation keys, is running Jelly Bean
    112      * or earlier, or translucent system UI modes have not been enabled in either
    113      * the theme or via window flags, then this method does nothing.
    114      *
    115      * @param enabled True to enable tinting, false to disable it (default).
    116      */
    117     public void setNavigationBarTintEnabled(boolean enabled) {
    118         mNavBarTintEnabled = enabled;
    119         if (mNavBarAvailable) {
    120             mNavBarTintView.setVisibility(enabled ? View.VISIBLE : View.GONE);
    121         }
    122     }
    123 
    124     /**
    125      * Apply the specified color tint to all system UI bars.
    126      *
    127      * @param color The color of the background tint.
    128      */
    129     public void setTintColor(int color) {
    130         setStatusBarTintColor(color);
    131         setNavigationBarTintColor(color);
    132     }
    133 
    134     /**
    135      * Apply the specified drawable or color resource to all system UI bars.
    136      *
    137      * @param res The identifier of the resource.
    138      */
    139     public void setTintResource(int res) {
    140         setStatusBarTintResource(res);
    141         setNavigationBarTintResource(res);
    142     }
    143 
    144     /**
    145      * Apply the specified drawable to all system UI bars.
    146      *
    147      * @param drawable The drawable to use as the background, or null to remove it.
    148      */
    149     public void setTintDrawable(Drawable drawable) {
    150         setStatusBarTintDrawable(drawable);
    151         setNavigationBarTintDrawable(drawable);
    152     }
    153 
    154     /**
    155      * Apply the specified alpha to all system UI bars.
    156      *
    157      * @param alpha The alpha to use
    158      */
    159     public void setTintAlpha(float alpha) {
    160         setStatusBarAlpha(alpha);
    161         setNavigationBarAlpha(alpha);
    162     }
    163 
    164     /**
    165      * Apply the specified color tint to the system status bar.
    166      *
    167      * @param color The color of the background tint.
    168      */
    169     public void setStatusBarTintColor(int color) {
    170         if (mStatusBarAvailable) {
    171             mStatusBarTintView.setBackgroundColor(color);
    172         }
    173     }
    174 
    175     /**
    176      * Apply the specified drawable or color resource to the system status bar.
    177      *
    178      * @param res The identifier of the resource.
    179      */
    180     public void setStatusBarTintResource(int res) {
    181         if (mStatusBarAvailable) {
    182             mStatusBarTintView.setBackgroundResource(res);
    183         }
    184     }
    185 
    186     /**
    187      * Apply the specified drawable to the system status bar.
    188      *
    189      * @param drawable The drawable to use as the background, or null to remove it.
    190      */
    191     @SuppressWarnings("deprecation")
    192     public void setStatusBarTintDrawable(Drawable drawable) {
    193         if (mStatusBarAvailable) {
    194             mStatusBarTintView.setBackgroundDrawable(drawable);
    195         }
    196     }
    197 
    198     /**
    199      * Apply the specified alpha to the system status bar.
    200      *
    201      * @param alpha The alpha to use
    202      */
    203     @TargetApi(11)
    204     public void setStatusBarAlpha(float alpha) {
    205         if (mStatusBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    206             mStatusBarTintView.setAlpha(alpha);
    207         }
    208     }
    209 
    210     /**
    211      * Apply the specified color tint to the system navigation bar.
    212      *
    213      * @param color The color of the background tint.
    214      */
    215     public void setNavigationBarTintColor(int color) {
    216         if (mNavBarAvailable) {
    217             mNavBarTintView.setBackgroundColor(color);
    218         }
    219     }
    220 
    221     /**
    222      * Apply the specified drawable or color resource to the system navigation bar.
    223      *
    224      * @param res The identifier of the resource.
    225      */
    226     public void setNavigationBarTintResource(int res) {
    227         if (mNavBarAvailable) {
    228             mNavBarTintView.setBackgroundResource(res);
    229         }
    230     }
    231 
    232     /**
    233      * Apply the specified drawable to the system navigation bar.
    234      *
    235      * @param drawable The drawable to use as the background, or null to remove it.
    236      */
    237     @SuppressWarnings("deprecation")
    238     public void setNavigationBarTintDrawable(Drawable drawable) {
    239         if (mNavBarAvailable) {
    240             mNavBarTintView.setBackgroundDrawable(drawable);
    241         }
    242     }
    243 
    244     /**
    245      * Apply the specified alpha to the system navigation bar.
    246      *
    247      * @param alpha The alpha to use
    248      */
    249     @TargetApi(11)
    250     public void setNavigationBarAlpha(float alpha) {
    251         if (mNavBarAvailable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    252             mNavBarTintView.setAlpha(alpha);
    253         }
    254     }
    255 
    256     /**
    257      * Get the system bar configuration.
    258      *
    259      * @return The system bar configuration for the current device configuration.
    260      */
    261     public SystemBarConfig getConfig() {
    262         return mConfig;
    263     }
    264 
    265     /**
    266      * Is tinting enabled for the system status bar?
    267      *
    268      * @return True if enabled, False otherwise.
    269      */
    270     public boolean isStatusBarTintEnabled() {
    271         return mStatusBarTintEnabled;
    272     }
    273 
    274     /**
    275      * Is tinting enabled for the system navigation bar?
    276      *
    277      * @return True if enabled, False otherwise.
    278      */
    279     public boolean isNavBarTintEnabled() {
    280         return mNavBarTintEnabled;
    281     }
    282 
    283     private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
    284         mStatusBarTintView = new View(context);
    285         LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
    286         params.gravity = Gravity.TOP;
    287         if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
    288             params.rightMargin = mConfig.getNavigationBarWidth();
    289         }
    290         mStatusBarTintView.setLayoutParams(params);
    291         mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
    292         mStatusBarTintView.setVisibility(View.GONE);
    293         decorViewGroup.addView(mStatusBarTintView);
    294     }
    295 
    296     private void setupNavBarView(Context context, ViewGroup decorViewGroup) {
    297         mNavBarTintView = new View(context);
    298         LayoutParams params;
    299         if (mConfig.isNavigationAtBottom()) {
    300             params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getNavigationBarHeight());
    301             params.gravity = Gravity.BOTTOM;
    302         } else {
    303             params = new LayoutParams(mConfig.getNavigationBarWidth(), LayoutParams.MATCH_PARENT);
    304             params.gravity = Gravity.RIGHT;
    305         }
    306         mNavBarTintView.setLayoutParams(params);
    307         mNavBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
    308         mNavBarTintView.setVisibility(View.GONE);
    309         decorViewGroup.addView(mNavBarTintView);
    310     }
    311 
    312     /**
    313      * Class which describes system bar sizing and other characteristics for the current
    314      * device configuration.
    315      *
    316      */
    317     public static class SystemBarConfig {
    318 
    319         private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
    320         private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
    321         private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
    322         private static final String NAV_BAR_WIDTH_RES_NAME = "navigation_bar_width";
    323         private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
    324 
    325         private final boolean mTranslucentStatusBar;
    326         private final boolean mTranslucentNavBar;
    327         private final int mStatusBarHeight;
    328         private final int mActionBarHeight;
    329         private final boolean mHasNavigationBar;
    330         private final int mNavigationBarHeight;
    331         private final int mNavigationBarWidth;
    332         private final boolean mInPortrait;
    333         private final float mSmallestWidthDp;
    334 
    335         private SystemBarConfig(Activity activity, boolean translucentStatusBar, boolean traslucentNavBar) {
    336             Resources res = activity.getResources();
    337             mInPortrait = (res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
    338             mSmallestWidthDp = getSmallestWidthDp(activity);
    339             mStatusBarHeight = getInternalDimensionSize(res, STATUS_BAR_HEIGHT_RES_NAME);
    340             mActionBarHeight = getActionBarHeight(activity);
    341             mNavigationBarHeight = getNavigationBarHeight(activity);
    342             mNavigationBarWidth = getNavigationBarWidth(activity);
    343             mHasNavigationBar = (mNavigationBarHeight > 0);
    344             mTranslucentStatusBar = translucentStatusBar;
    345             mTranslucentNavBar = traslucentNavBar;
    346         }
    347 
    348         @TargetApi(14)
    349         private int getActionBarHeight(Context context) {
    350             int result = 0;
    351             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    352                 TypedValue tv = new TypedValue();
    353                 context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true);
    354                 result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
    355             }
    356             return result;
    357         }
    358 
    359         @TargetApi(14)
    360         private int getNavigationBarHeight(Context context) {
    361             Resources res = context.getResources();
    362             int result = 0;
    363             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    364                 if (hasNavBar(context)) {
    365                     String key;
    366                     if (mInPortrait) {
    367                         key = NAV_BAR_HEIGHT_RES_NAME;
    368                     } else {
    369                         key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
    370                     }
    371                     return getInternalDimensionSize(res, key);
    372                 }
    373             }
    374             return result;
    375         }
    376 
    377         @TargetApi(14)
    378         private int getNavigationBarWidth(Context context) {
    379             Resources res = context.getResources();
    380             int result = 0;
    381             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
    382                 if (hasNavBar(context)) {
    383                     return getInternalDimensionSize(res, NAV_BAR_WIDTH_RES_NAME);
    384                 }
    385             }
    386             return result;
    387         }
    388 
    389         @TargetApi(14)
    390         private boolean hasNavBar(Context context) {
    391             Resources res = context.getResources();
    392             int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
    393             if (resourceId != 0) {
    394                 boolean hasNav = res.getBoolean(resourceId);
    395                 // check override flag (see static block)
    396                 if ("1".equals(sNavBarOverride)) {
    397                     hasNav = false;
    398                 } else if ("0".equals(sNavBarOverride)) {
    399                     hasNav = true;
    400                 }
    401                 return hasNav;
    402             } else { // fallback
    403                 return !ViewConfiguration.get(context).hasPermanentMenuKey();
    404             }
    405         }
    406 
    407         private int getInternalDimensionSize(Resources res, String key) {
    408             int result = 0;
    409             int resourceId = res.getIdentifier(key, "dimen", "android");
    410             if (resourceId > 0) {
    411                 result = res.getDimensionPixelSize(resourceId);
    412             }
    413             return result;
    414         }
    415 
    416         @SuppressLint("NewApi")
    417         private float getSmallestWidthDp(Activity activity) {
    418             DisplayMetrics metrics = new DisplayMetrics();
    419             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    420                 activity.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
    421             } else {
    422                 // TODO this is not correct, but we don't really care pre-kitkat
    423                 activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
    424             }
    425             float widthDp = metrics.widthPixels / metrics.density;
    426             float heightDp = metrics.heightPixels / metrics.density;
    427             return Math.min(widthDp, heightDp);
    428         }
    429 
    430         /**
    431          * Should a navigation bar appear at the bottom of the screen in the current
    432          * device configuration? A navigation bar may appear on the right side of
    433          * the screen in certain configurations.
    434          *
    435          * @return True if navigation should appear at the bottom of the screen, False otherwise.
    436          */
    437         public boolean isNavigationAtBottom() {
    438             return (mSmallestWidthDp >= 600 || mInPortrait);
    439         }
    440 
    441         /**
    442          * Get the height of the system status bar.
    443          *
    444          * @return The height of the status bar (in pixels).
    445          */
    446         public int getStatusBarHeight() {
    447             return mStatusBarHeight;
    448         }
    449 
    450         /**
    451          * Get the height of the action bar.
    452          *
    453          * @return The height of the action bar (in pixels).
    454          */
    455         public int getActionBarHeight() {
    456             return mActionBarHeight;
    457         }
    458 
    459         /**
    460          * Does this device have a system navigation bar?
    461          *
    462          * @return True if this device uses soft key navigation, False otherwise.
    463          */
    464         public boolean hasNavigtionBar() {
    465             return mHasNavigationBar;
    466         }
    467 
    468         /**
    469          * Get the height of the system navigation bar.
    470          *
    471          * @return The height of the navigation bar (in pixels). If the device does not have
    472          * soft navigation keys, this will always return 0.
    473          */
    474         public int getNavigationBarHeight() {
    475             return mNavigationBarHeight;
    476         }
    477 
    478         /**
    479          * Get the width of the system navigation bar when it is placed vertically on the screen.
    480          *
    481          * @return The width of the navigation bar (in pixels). If the device does not have
    482          * soft navigation keys, this will always return 0.
    483          */
    484         public int getNavigationBarWidth() {
    485             return mNavigationBarWidth;
    486         }
    487 
    488         /**
    489          * Get the layout inset for any system UI that appears at the top of the screen.
    490          *
    491          * @param withActionBar True to include the height of the action bar, False otherwise.
    492          * @return The layout inset (in pixels).
    493          */
    494         public int getPixelInsetTop(boolean withActionBar) {
    495             return (mTranslucentStatusBar ? mStatusBarHeight : 0) + (withActionBar ? mActionBarHeight : 0);
    496         }
    497 
    498         /**
    499          * Get the layout inset for any system UI that appears at the bottom of the screen.
    500          *
    501          * @return The layout inset (in pixels).
    502          */
    503         public int getPixelInsetBottom() {
    504             if (mTranslucentNavBar && isNavigationAtBottom()) {
    505                 return mNavigationBarHeight;
    506             } else {
    507                 return 0;
    508             }
    509         }
    510 
    511         /**
    512          * Get the layout inset for any system UI that appears at the right of the screen.
    513          *
    514          * @return The layout inset (in pixels).
    515          */
    516         public int getPixelInsetRight() {
    517             if (mTranslucentNavBar && !isNavigationAtBottom()) {
    518                 return mNavigationBarWidth;
    519             } else {
    520                 return 0;
    521             }
    522         }
    523 
    524     }
    525 
    526 }
    背景图全屏时,需要设置isFitsSystemWindows
  • 相关阅读:
    Ocelot网关
    .Net Configuration配置优先级问题
    FilterContext/HttpContext 获取请求参数
    关于.Net的文件上传问题
    Notion+Zetero文献同步配置
    PyTorch训练模版
    marked ASP.NET 页面对象模型
    转:jQuery设计思想
    tryParse, try/catch(Parse), Convert比较
    CSS3 :nthchild()伪类选择器
  • 原文地址:https://www.cnblogs.com/CharlesGrant/p/4944645.html
Copyright © 2011-2022 走看看