0
点赞
收藏
分享

微信扫一扫

Android沉浸式全屏讲解(状态栏、导航栏处理)

Android应用中经常会有一些要求全屏显隐状态栏导航栏的需求。通过全屏沉浸式的处理可以让应用达到更好的显示效果。下面系统的讲解一下有关全屏,隐藏状态栏导航栏,沉浸式的知识。

在Android4.1之前只能隐藏状态栏,在Android4.1以及之后Android提供了一套控制SystemUI的方式,重点放在第二部分。

在Android4.1之前隐藏状态栏

在Android4.1之前你可以通过设置WindowManager来隐藏状态栏。你可以通过编码来实现,也可以通过在manifest文件中给activity设置theme来实现。
如果你要设置activity的状态栏一直处于隐藏状态,那么在manifest设置的方式是你的首选方式(尽管也可以使用编程方式。)。实现方式如下。

<application
...
android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >

...
</application>

使用manifest设置的方式有以下优点:

  1. 比编程方式更加容易维护,更不容易出错。

  2. 会有一个更加平滑的过渡,因为在实例化activity之前系统就已经拥有了呈现UI所需的信息。

另外,也可以以编程方式设置WindowsManager标志。这种方法使用户在与应用程序交互时更容易隐藏和显示状态栏。

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// If the Android version is lower than Jellybean, use this call to hide
// the status bar.
if (Build.VERSION.SDK_INT < 16) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
setContentView(R.layout.activity_main);
}
...
}

当你设置WindowsManager标志时(无论是通过theme还是以编程方式),除非您的应用程序清除了这些标志,否则这些标志将保持有效。

可以使用FLAG_LAYOUT_IN_SCREEN将activity布局设置为使用相同的屏幕区域。当你启用FLAG_FILLSCREEN时,可以使用相同的屏幕区域。这将防止在状态栏隐藏和显示时调整内容的大小。

设置全屏

在Android4.1以及更高版本可以使用setSystemUiVisibility来控制SystemUI,为了更系统的讲解,不分别按照效果来讲,而是把用到的flag先列出来一起讲。以下flag经过互相组合能达到全屏隐藏状态栏,全屏隐藏导航栏,全屏显示状态栏导航栏等很多不同效果。

控制SystemBar相关:

  • SYSTEM_UI_FLAG_FULLSCREEN

  • SYSTEM_UI_FLAG_HIDE_NAVIGATION

  • SYSTEM_UI_FLAG_LOW_PROFILE

布局相关:

  • SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

  • SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

  • SYSTEM_UI_FLAG_LAYOUT_STABLE

沉浸式相关 (4.4 引入):

  • SYSTEM_UI_IMMERSIVE

  • SYSTEM_UI_IMMERSIVE_STICKY

控制 SystemBar 相关

SYSTEM_UI_FLAG_FULLSCREEN
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView.setSystemUiVisibility(uiOptions);
getSupportActionBar().hide();

通过以上代码可以实现隐藏状态栏。为了显示出全屏效果,建议同时将ActionBar隐藏掉。仅设置这一条属性,显示效果存在以下特性。

  • 当滑动system bar、点击home键menu键就会清除掉flag,状态栏会重新显示出来。

  • 并且布局也会随着状态栏的显隐进行布局调整进行重绘。

效果图

SYSTEM_UI_HIDE_NAVIGATION
View decorView2 = getWindow().getDecorView();
int uiOptions2 = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN;
decorView2.setSystemUiVisibility(uiOptions2);
getSupportActionBar().hide();

以上代码可以实现隐藏状态栏和导航栏。
尽管可以仅仅隐藏导航栏,但是建议隐藏导航栏的时候将状态栏一并隐藏,以达到更好的沉浸效果。

  • 与隐藏状态栏不同的是点击任意布局中的任意位置都会导致导航栏导航栏重新显示出来。

  • 并且布局也会随着状态栏导航栏的显隐进行布局调整进行重绘。

SYSTEM_UI_LOW_PROFILE

View decorView7 = getWindow().getDecorView();
int uiOptions7 = View.SYSTEM_UI_FLAG_LOW_PROFILE;
decorView7.setSystemUiVisibility(uiOptions7);

布局相关

SYSTEM_UI_FLAG_LAYOUT_STABLE
View decorView8 = getWindow().getDecorView();
int uiOptions8 = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView8.setSystemUiVisibility(uiOptions8);
getSupportActionBar().hide();

以上代码设置了隐藏状态栏和SYSTEM_UI_FLAG_LAYOUT_STABLE两个flag,显示效果为隐藏状态栏,布局稳定。但是布局不延伸到全屏,效果看起来还是很奇葩的。

  • 当滑动systembar、点击home键多任务键就会清除掉flag。状态栏会重新显示出来。

  • 布局不会随着状态栏的显隐进行调整变化。

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
View decorView3 = getWindow().getDecorView();
int uiOptions3 = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView3.setSystemUiVisibility(uiOptions3);
getSupportActionBar().hide();

以上代码显示出来的效果和上一段代码相比,布局延伸到了状态栏的位置。

  • 当滑动systembar、点击home键menu键就会清除掉flag。状态栏会重新显示出来。

  • 布局不会随着状态栏的显隐进行调整变化

SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
View decorView4 = getWindow().getDecorView();
int uiOptions4 = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView4.setSystemUiVisibility(uiOptions4);
getSupportActionBar().hide();

以上代码的显示效果是状态栏和导航栏隐藏,布局延伸到了状态栏和导航栏的位置。

  • 点击任意布局就会清除掉flag。状态栏导航栏会重新显示出来。

  • 布局不会随着状态栏导航栏的显隐进行调整变化。

在设置了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN、SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION flag的情况,如果把状态栏导航栏颜色设置为透明,则会有透明的状态栏导航栏覆盖在布局上的效果。这也证明了即便布局状态栏导航栏出来了,布局也确实延伸到了状态栏导航栏的位置。

沉浸式相关

SYSTEM_UI_IMMERSIVE
View decorView5 = getWindow().getDecorView();
int uiOptions5 = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE;
decorView5.setSystemUiVisibility(uiOptions5);
getSupportActionBar().hide();

以上代码的显示效果。

  • 隐藏状态栏、导航栏。

  • 布局延伸到了状态栏、导航栏的位置。

  • 布局稳定显示,不会因为状态栏的显隐来调整布局。

  • 当手动调出状态栏导航栏的时候,flag才会被清除。

SYSTEM_UI_IMMERSIVE_STICKY
View decorView6 = getWindow().getDecorView();
int uiOptions6 = View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView6.setSystemUiVisibility(uiOptions6);
getSupportActionBar().hide();

以上代码的显示效果。

  • 隐藏状态栏、导航栏

  • 布局延伸到了状态栏、导航栏的位置。

  • 布局稳定显示,不会因为状态栏的显隐来调整布局。

  • 手动调出的状态栏导航栏会半透明显示覆盖在界面上,随后还会隐藏掉。

  • 如果离开页面还是会导致flag被清除,效果消失。

对于flag被清除问题,重设的位置可以放在onWindowFocusChanged中。

想要清除flag可以直接调用setSystemUiVisibility(0);

小总结

public void setFullscreen(boolean isShowStatusBar, boolean isShowNavigationBar) {
int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

if (!isShowStatusBar) {
uiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
}
if (!isShowNavigationBar) {
uiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
}
getWindow().getDecorView().setSystemUiVisibility(uiOptions);

//隐藏标题栏
getSupportActionBar().hide();
//专门设置一下状态栏导航栏背景颜色为透明,凸显效果。
setNavigationStatusColor(Color.TRANSPARENT);
}

public void setNavigationStatusColor(int color) {
//VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
if (Build.VERSION.SDK_INT >= 21) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setNavigationBarColor(color);
getWindow().setStatusBarColor(color);
}
}

监听状态栏导航栏的变化

View decorView = getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener
(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
// Note that system bars will only be "visible" if none of the
// LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
// TODO: The system bars are visible. Make any desired
// adjustments to your UI, such as showing the action bar or
// other navigational controls.
} else {
// TODO: The system bars are NOT visible. Make any desired
// adjustments to your UI, such as hiding the action bar or
// other navigational controls.
}
}
});

上面代码和注释可以说写的很清楚了。可以在onSystemUiVisibilityChange接口中通过判断LOW_PROFILE,HIDE_NAVIGATION和FULLSCREEN的值来看显隐,0为显示,1为隐藏。

最后

  • Task is cheap. Show me the code. github地址: https://github.com/qiaoshouqing/fullscreen

  • 内容主要参考谷歌官方文档,不得不说文章还是原生的好,在国内很难搜到好用的文章。 https://developer.android.com/training/system-ui/index.html

  • 后来发现国内有人翻译过了,文章写作方式上有参考。https://blog.csdn.net/adzcsx2/article/details/53031950

举报

相关推荐

0 条评论