你的位置:首页 > 操作系统

[操作系统][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 purposes101    * here. This allows your UI to continually hide the status bar, while still102    * using the system UI flags to hide the action bar while still retaining103    * a stable layout. Note that changing the window fullscreen flag will never104    * provide a stable layout for a clean transition.105    *106    * <p>If you are using ActionBar in107    * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY108    * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the109    * 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 window115    * to be layed out as if it has requested116    * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This117    * allows it to avoid artifacts when switching in and out of that mode, at118    * the expense that some of its user interface may be covered by screen119    * decorations when they are shown. You can perform layout of your inner120    * UI elements to account for the navigation system UI through the121    * {@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 window127    * to be layed out as if it has requested128    * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This129    * allows it to avoid artifacts when switching in and out of that mode, at130    * the expense that some of its user interface may be covered by screen131    * decorations when they are shown. You can perform layout of your inner132    * UI elements to account for non-fullscreen system UI through the133    * {@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 when139    * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is140    * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any141    * user interaction.142    * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only143    * 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 when149    * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation150    * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive151    * 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 user153    * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system154    * 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 with156    * system gestures, such as swiping from the top of the screen. These transient system bars157    * will overlay app’s content, may have some degree of transparency, and will automatically158    * hide after a short timeout.159    * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and160    * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination161    * 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    * @hide177    *178    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked179    * 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 also182    * 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    * @hide188    *189    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked190    * 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    * @hide198    *199    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked200    * 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 block203    * 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    * @hide209    *210    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked211    * 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 that214    * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies215    * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.216   */217   public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;218 219   /**220    * @hide221    *222    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked223    * 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    * @hide231    *232    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked233    * 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 this236    * 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    * @hide242    *243    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked244    * 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 this247    * 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    * @hide253    *254    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked255    * 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 has258    * its own clock making the status bar's clock redundant.259   */260   public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;261 262   /**263    * @hide264    *265    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked266    * 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 this269    * 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    * @hide275    *276    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked277    * 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 this280    * 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    * @hide286    *287    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked288    * 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    * @hide296    *297    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked298    * 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    * @hide306    *307    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked308    * 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    * @hide316    *317    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked318    * 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    * @hide326    *327    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked328    * 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    * @hide336    *337    * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked338    * 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    * @hide346   */347   public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;

标识位源码,5.0的SDK内容比原来的多了不少

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

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

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

SYSTEM_UI_FLAG_FULLSCREENbar存在,内容消失 显示一个点
SYSTEM_UI_FLAG_HIDE_NAVIGATIONnavigation_bar消失
SYSTEM_UI_FLAG_FULLSCREENstatus_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状态栏的一点新理解。若不正确,但求拍砖。

 

参考:

动态显示和隐藏状态栏