• [Android] 状态栏的一些认识


    前段时间遇到几个关于状态栏的问题,又了解了一下状态栏相关的知识,现在做一下记录。

    本文地址:http://www.cnblogs.com/rossoneri/p/4316343.html 

    前戏和问题

    首先一般的设备都含有两个bar:顶部的状态栏(statusbar)和底部的工具栏(NavigationBar),关于这两个Bar我最初的认识在于之前的文章:

    [Android]获取系统顶部状态栏(StatusBar)与底部工具栏(NavigationBar)的高度

    通过之前文章的方法就可以获取屏幕高度,来对界面进行一番设计。但后来我突然发现了一个棘手的新问题,我遇到了这么一个蛋疼的界面:

    它竟然把两个Bar合并到一起了。。。我去。。

    因为之前的一个控件设计是考虑了上下两条Bar的高度,然后相对顶部工具栏来进行计算,结果遇上这么个屏幕,界面的控件纵向显示就出现了小的偏移,大概30dp左右。

    好了,问题来了,那就着手解决吧。

    思考和解决

    既然你把上下的Bar合并在一起,那么原来顶部的statusbar是隐藏了么?

    我先用前文提到的方法试试输出顶部状态栏的高度,结果得到一个高度,是25。嗯,跟我看到的大概30dp高度差不多,也就是说顶部状态栏高度是存在的。那是被隐藏了么?

    想知道这个,就需要找找Android是否有提供一个获取statusbar显示状态的方法。查了查API,找到了一个方法:

     int n = mActivity.getWindow().getDecorView().getSystemUiVisibility();

    结果得到 n =  0 

    看了看 0 的含义:

        /**
         * Special constant for {@link #setSystemUiVisibility(int)}: View has
         * requested the system UI (status bar) to be visible (the default).
         *
         * @see #setSystemUiVisibility(int)
         */
        public static final int SYSTEM_UI_FLAG_VISIBLE = 0;

    也就是说顶部的statusbar是默认的可见状态。WTF,我明明看不见了,你竟然说还是默认的显示状态。好吧,难道这个statusbar移到底部合并 显示 了吗?但高度不对呀。

    带着疑问,我又试着输出底部工具栏高度,得到了48。跟之前的设备一样,底部的高度没有变。

    得,说到底,两条Bar的高度是都可以获取到的,而且值和正常的一样,虽然顶部的看不见,但状态还是默认的可见的,显示成这个样式是系统定制时设定的。姑且这么理解吧。

    既然底部的工具栏高度没有变化,我的控件就重新以底部为参照来计算好了。用这个方法,暂且解决了控件显示位置的问题。

    拓展知识

    经过上面的问题,好歹是解决了眼前的bug。趁着看到这一块,我就又多了解了一下表示bar状态的几个标识:

      1 /**
      2      * Special constant for {@link #setSystemUiVisibility(int)}: View has
      3      * requested the system UI (status bar) to be visible (the default).
      4      *
      5      * @see #setSystemUiVisibility(int)
      6      */
      7     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
      8 
      9     /**
     10      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
     11      * system UI to enter an unobtrusive "low profile" mode.
     12      *
     13      * <p>This is for use in games, book readers, video players, or any other
     14      * "immersive" application where the usual system chrome is deemed too distracting.
     15      *
     16      * <p>In low profile mode, the status bar and/or navigation icons may dim.
     17      *
     18      * @see #setSystemUiVisibility(int)
     19      */
     20     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
     21 
     22     /**
     23      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
     24      * system navigation be temporarily hidden.
     25      *
     26      * <p>This is an even less obtrusive state than that called for by
     27      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
     28      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
     29      * those to disappear. This is useful (in conjunction with the
     30      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
     31      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
     32      * window flags) for displaying content using every last pixel on the display.
     33      *
     34      * <p>There is a limitation: because navigation controls are so important, the least user
     35      * interaction will cause them to reappear immediately.  When this happens, both
     36      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
     37      * so that both elements reappear at the same time.
     38      *
     39      * @see #setSystemUiVisibility(int)
     40      */
     41     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
     42 
     43     /**
     44      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
     45      * into the normal fullscreen mode so that its content can take over the screen
     46      * while still allowing the user to interact with the application.
     47      *
     48      * <p>This has the same visual effect as
     49      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
     50      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
     51      * meaning that non-critical screen decorations (such as the status bar) will be
     52      * hidden while the user is in the View's window, focusing the experience on
     53      * that content.  Unlike the window flag, if you are using ActionBar in
     54      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
     55      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
     56      * hide the action bar.
     57      *
     58      * <p>This approach to going fullscreen is best used over the window flag when
     59      * it is a transient state -- that is, the application does this at certain
     60      * points in its user interaction where it wants to allow the user to focus
     61      * on content, but not as a continuous state.  For situations where the application
     62      * would like to simply stay full screen the entire time (such as a game that
     63      * wants to take over the screen), the
     64      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
     65      * is usually a better approach.  The state set here will be removed by the system
     66      * in various situations (such as the user moving to another application) like
     67      * the other system UI states.
     68      *
     69      * <p>When using this flag, the application should provide some easy facility
     70      * for the user to go out of it.  A common example would be in an e-book
     71      * reader, where tapping on the screen brings back whatever screen and UI
     72      * decorations that had been hidden while the user was immersed in reading
     73      * the book.
     74      *
     75      * @see #setSystemUiVisibility(int)
     76      */
     77     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
     78 
     79     /**
     80      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
     81      * flags, we would like a stable view of the content insets given to
     82      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
     83      * will always represent the worst case that the application can expect
     84      * as a continuous state.  In the stock Android UI this is the space for
     85      * the system bar, nav bar, and status bar, but not more transient elements
     86      * such as an input method.
     87      *
     88      * The stable layout your UI sees is based on the system UI modes you can
     89      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
     90      * then you will get a stable layout for changes of the
     91      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
     92      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
     93      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
     94      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
     95      * with a stable layout.  (Note that you should avoid using
     96      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
     97      *
     98      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
     99      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
    100      * then a hidden status bar will be considered a "stable" state for purposes
    101      * here.  This allows your UI to continually hide the status bar, while still
    102      * using the system UI flags to hide the action bar while still retaining
    103      * a stable layout.  Note that changing the window fullscreen flag will never
    104      * provide a stable layout for a clean transition.
    105      *
    106      * <p>If you are using ActionBar in
    107      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
    108      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
    109      * insets it adds to those given to the application.
    110      */
    111     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
    112 
    113     /**
    114      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
    115      * to be layed out as if it has requested
    116      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
    117      * allows it to avoid artifacts when switching in and out of that mode, at
    118      * the expense that some of its user interface may be covered by screen
    119      * decorations when they are shown.  You can perform layout of your inner
    120      * UI elements to account for the navigation system UI through the
    121      * {@link #fitSystemWindows(Rect)} method.
    122      */
    123     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
    124 
    125     /**
    126      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
    127      * to be layed out as if it has requested
    128      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
    129      * allows it to avoid artifacts when switching in and out of that mode, at
    130      * the expense that some of its user interface may be covered by screen
    131      * decorations when they are shown.  You can perform layout of your inner
    132      * UI elements to account for non-fullscreen system UI through the
    133      * {@link #fitSystemWindows(Rect)} method.
    134      */
    135     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
    136 
    137     /**
    138      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
    139      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
    140      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
    141      * user interaction.
    142      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
    143      * has an effect when used in combination with that flag.</p>
    144      */
    145     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
    146 
    147     /**
    148      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
    149      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
    150      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
    151      * experience while also hiding the system bars.  If this flag is not set,
    152      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
    153      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
    154      * if the user swipes from the top of the screen.
    155      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
    156      * system gestures, such as swiping from the top of the screen.  These transient system bars
    157      * will overlay app’s content, may have some degree of transparency, and will automatically
    158      * hide after a short timeout.
    159      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
    160      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
    161      * with one or both of those flags.</p>
    162      */
    163     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
    164 
    165     /**
    166      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
    167      */
    168     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
    169 
    170     /**
    171      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
    172      */
    173     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
    174 
    175     /**
    176      * @hide
    177      *
    178      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    179      * out of the public fields to keep the undefined bits out of the developer's way.
    180      *
    181      * Flag to make the status bar not expandable.  Unless you also
    182      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
    183      */
    184     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
    185 
    186     /**
    187      * @hide
    188      *
    189      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    190      * out of the public fields to keep the undefined bits out of the developer's way.
    191      *
    192      * Flag to hide notification icons and scrolling ticker text.
    193      */
    194     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
    195 
    196     /**
    197      * @hide
    198      *
    199      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    200      * out of the public fields to keep the undefined bits out of the developer's way.
    201      *
    202      * Flag to disable incoming notification alerts.  This will not block
    203      * icons, but it will block sound, vibrating and other visual or aural notifications.
    204      */
    205     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
    206 
    207     /**
    208      * @hide
    209      *
    210      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    211      * out of the public fields to keep the undefined bits out of the developer's way.
    212      *
    213      * Flag to hide only the scrolling ticker.  Note that
    214      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
    215      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
    216      */
    217     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
    218 
    219     /**
    220      * @hide
    221      *
    222      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    223      * out of the public fields to keep the undefined bits out of the developer's way.
    224      *
    225      * Flag to hide the center system info area.
    226      */
    227     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
    228 
    229     /**
    230      * @hide
    231      *
    232      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    233      * out of the public fields to keep the undefined bits out of the developer's way.
    234      *
    235      * Flag to hide only the home button.  Don't use this
    236      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
    237      */
    238     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
    239 
    240     /**
    241      * @hide
    242      *
    243      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    244      * out of the public fields to keep the undefined bits out of the developer's way.
    245      *
    246      * Flag to hide only the back button. Don't use this
    247      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
    248      */
    249     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
    250 
    251     /**
    252      * @hide
    253      *
    254      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    255      * out of the public fields to keep the undefined bits out of the developer's way.
    256      *
    257      * Flag to hide only the clock.  You might use this if your activity has
    258      * its own clock making the status bar's clock redundant.
    259      */
    260     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
    261 
    262     /**
    263      * @hide
    264      *
    265      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    266      * out of the public fields to keep the undefined bits out of the developer's way.
    267      *
    268      * Flag to hide only the recent apps button. Don't use this
    269      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
    270      */
    271     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
    272 
    273     /**
    274      * @hide
    275      *
    276      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    277      * out of the public fields to keep the undefined bits out of the developer's way.
    278      *
    279      * Flag to disable the global search gesture. Don't use this
    280      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
    281      */
    282     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
    283 
    284     /**
    285      * @hide
    286      *
    287      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    288      * out of the public fields to keep the undefined bits out of the developer's way.
    289      *
    290      * Flag to specify that the status bar is displayed in transient mode.
    291      */
    292     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
    293 
    294     /**
    295      * @hide
    296      *
    297      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    298      * out of the public fields to keep the undefined bits out of the developer's way.
    299      *
    300      * Flag to specify that the navigation bar is displayed in transient mode.
    301      */
    302     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
    303 
    304     /**
    305      * @hide
    306      *
    307      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    308      * out of the public fields to keep the undefined bits out of the developer's way.
    309      *
    310      * Flag to specify that the hidden status bar would like to be shown.
    311      */
    312     public static final int STATUS_BAR_UNHIDE = 0x10000000;
    313 
    314     /**
    315      * @hide
    316      *
    317      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    318      * out of the public fields to keep the undefined bits out of the developer's way.
    319      *
    320      * Flag to specify that the hidden navigation bar would like to be shown.
    321      */
    322     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
    323 
    324     /**
    325      * @hide
    326      *
    327      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    328      * out of the public fields to keep the undefined bits out of the developer's way.
    329      *
    330      * Flag to specify that the status bar is displayed in translucent mode.
    331      */
    332     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
    333 
    334     /**
    335      * @hide
    336      *
    337      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
    338      * out of the public fields to keep the undefined bits out of the developer's way.
    339      *
    340      * Flag to specify that the navigation bar is displayed in translucent mode.
    341      */
    342     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
    343 
    344     /**
    345      * @hide
    346      */
    347     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
    标识位源码,5.0的SDK内容比原来的多了不少

    关于几个常用的我挨个试验了一下

    getWindow().getDecorView().setSystemUiVisibility(标识)

    然后操作了一下程序,得到下面的初步结论:

    SYSTEM_UI_FLAG_FULLSCREEN bar存在,内容消失 显示一个点
    SYSTEM_UI_FLAG_HIDE_NAVIGATION navigation_bar消失
    SYSTEM_UI_FLAG_FULLSCREEN status_bar消失
    SYSTEM_UI_FLAG_LAYOUT_STABLE 不变
    SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION 上下bar还在,但显示的内容拓展到被bar盖住的区域了好像
    SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 上下bar还在,显示的内容拓展到上面bar的位置
    SYSTEM_UI_FLAG_IMMERSIVE 不变
    SYSTEM_UI_FLAG_IMMERSIVE_STICKY 不变

    可以结合着源码里的官方注释来看看
     

    一个新问题

     看完这,我突然想起来之前遇到的另一个问题:

    我写了一个popupwindow,希望它在靠上的位置弹出来时这么显示

     结果它是这么显示的:

    哎我去,当时我真是百思不得其解,因为各种高度我都考虑到,写到计算代码里,意思是一旦遇到顶部显示的情况,popupwindow就自动向下偏移一个距离完整显示。

    另外,popupwindow作为一个弹出时单独在最上层显示的控件,就算我不控制它,它也不应该显示一半吧。

    后来我实在没办法就强行在代码里增加了35左右的高度好让它完整显示。

    现在看来,原来是界面显示的时候,顶部边界并不是状态栏的bottom,而是整个屏幕的顶部。出现这个情况是因为statusbar盖住了上面的一部分而已,只是我不知道罢了。。

    好了,下次设计界面的时候我会注意把statusbar的高度减掉的。。。

    以上就是我对Android状态栏的一点新理解。若不正确,但求拍砖。

    参考:

    动态显示和隐藏状态栏

  • 相关阅读:
    前端面试攻略1------算法部分
    MongoDB学习
    MongoDB作为Windows服务来安装 错误1053:服务没有及时响应启动或控制请求
    Vue 入门之 Vuex 实战
    Vue 路由详解
    vue入门全局配置
    VSCode配合ESLint自动修复格式化
    vue入门之单文件组件
    Echarts图表-学习
    GoJS学习
  • 原文地址:https://www.cnblogs.com/rossoneri/p/4316343.html
Copyright © 2020-2023  润新知