之前有做过一个需求,在某一个界面隐藏掉home,主页,返回键这几个虚拟按键以及状态栏,就是要全屏显示,刚开始隐藏了,但是在有用户交互的时候,导航键又显示出来了,纠结了下,最后解决了,现在总结下
1.首先说点其他的,如果你是修改源码,想去掉系统的虚拟按键,在任何界面都不显示的话,可以这样修改:
在system.prop文件里面
# temporary enables NAV bar (soft keys)
qemu.hw.mainkeys=1
qemu.hw.mainkeys这个字段值为0就是显示,值为1就不显示
2.接下来再说下只在某一个界面隐藏导航键和状态栏的方法
WindowManager mWindowManager = (WindowManager)this.mContext.getSystemService(this.mContext.WINDOW_SERVICE);
WindowManager.LayoutParams wmParams = new WindowManager.LayoutParams(); wmParams.format = PixelFormat.RGBA_8888;
如果设置为:
wmParams.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.INVISIBLE | View.SYSTEM_UI_FLAG_FULLSCREEN;
wmParams.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL|WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 这样可以暂时隐藏,但是当有用户交互点击屏幕的时候,导航键就又显示出来了。
我们来看下源码里面关于SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION的注释 There is a limitation: because navigation controls are so important, the least user
* interaction will cause them to reappear immediately. When this happens, both
* this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
* so that both elements reappear at the same time.
*
* @see #setSystemUiVisibility(int)
*/
public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
就是说android系统有一个限制:因为navigation的控制是很重要的,用户交互会让它们又重新显示出来,这个时候我们设置的SYSTEM_UI_FLAG_FULLSCREEN 和SYSTEM_UI_FLAG_HIDE_NAVIGATION都会自动被清除掉,所以虚拟键又会重新出现。
解决方法:
我们将wmParams.systemUiVisibility这个属性设置成下面这样的
wmParams.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.INVISIBLE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View .SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
wmParams.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL|WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
这样就可以实现了,接下来分析下:
我们来看下源码里面关于SYSTEM_UI_FLAG_IMMERSIVE这个flag的解释
/**
* Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
* hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. If this flag is
* not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
* user interaction.
* <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
* has an effect when used in combination with that flag.</p>
*/
public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
意思就是当setSystemUiVisibility只设置SYSTEM_UI_FLAG_HIDE_NAVIGATION这个属性时,View仍然会保持交互,如果不设置SYSTEM_UI_FLAG_IMMERSIVE这个flag的话,在有任何用户交互的情况下,SYSTEM_UI_FLAG_HIDE_NAVIGATION就会被清除掉。因此只有当SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_IMMERSIVE这两个flag一起使用的时候才会有效果。
再来看下源码里面关于SYSTEM_UI_FLAG_IMMERSIVE_STICKY这个flag的解释
/**
* Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
* hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
* bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. Use this flag to create an immersive
* experience while also hiding the system bars. If this flag is not set,
* {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
* interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
* if the user swipes from the top of the screen.
* <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
* system gestures, such as swiping from the top of the screen. These transient system bars
* will overlay app鈥檚 content, may have some degree of transparency, and will automatically
* hide after a short timeout.
* </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
* {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
* with one or both of those flags.</p>
*/
public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
这个跟SYSTEM_UI_FLAG_IMMERSIVE这个属性差不多,解释及自己看,为了设置的flag在有用户交互的时候不被强制清除,因此这个属性要配合SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION一起使用才会有效果。
wmParams.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.INVISIBLE | View.SYSTEM_UI_FLAG_FULLSCREEN|SYSTEM_UI_FLAG_IMMERSIVE_STICKY这个应该就会有效果了,当然为了保险起见,我把所有相关的属性都加上去了。
总结:
当我们设置某个属性或者使用某个api函数达不到预期的效果的时候,我们可以看下源码或者api文档,这样就可以找出问题的原因,从而加以解决。