Activity 全屏,沉浸式模式这一篇就够了
来源:互联网 发布:淘宝联盟的优惠券在哪 编辑:程序博客网 时间:2024/06/06 13:25
本文转载自 http://blog.csdn.net/zhangqinghuazhangzhe/article/details/52935290
第一次在项目中要用到全屏功能的时候无从下手,然后就是去百度了。百度到的结果都是差不多的。不过直接把代码贴过来的确是可以用的。但是除了知道怎么做之外还想去理解它,因为只有理解了才能举一反三嘛。好在在后来的时候看到了官方的文档,写的非常详细。
–> 我是官方文档 <–
接下来开始正题
…
…
…
先给出一些名词方便下面的讲解
StatusBar
NavigationBar
SystemBar – StatusBar 跟 NavigationBar 的统称
设置全屏主要分为两种方式:
- 4.0 之前采用的方式
- 4.0 之后新增的方式
4.0 以及之前设置全屏
因为 4.0 之前的系统已经很少了,所以这里就简单的说一下。
有两种方式可以实现全屏:
- 使用全屏的主题
- getWindow().addFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN);
这种全屏方式是无法隐藏 NavigationBar 的(如果有 NavigationBar 的话),因为 NavigationBar 是在 4.0 以后才引入的。使用这种方式设置全屏的特点是,离开了 App 后再进入 App 时,依然处于全屏模式,只能清除掉全屏标志位才能退出全屏。
4.1 以及之后设置全屏
4.1 以及之后使用 View 的 setSystemUiVisibility()
来对 SystemBar 进行控制。
任何 View 都可以用来调用这个方法,只要它是可见状态的。
下面先把要涉及到的 flag 分组列举出来(所有的 flag 都是以 SYSTEM_UI_FLAG 作为前缀,所以下面将其省略)。
控制 SystemBar 相关:
- FULLSCREEN
- HIDE_NAVIGATION
- LOW_PROFILE
布局相关:
- LAYOUT_SCREEN
- LAYOUT_HIDE_NAVIGATION
- LAYOUT_STABLE
沉浸式相关 (4.4 引入):
- IMMERSIVE
- IMMERSIVE_STICKY
超前提示:
在离开 App 时,比如按了 home / 多任务键 会导致设置的控制 SystemBar 相关的 flag 被清除,而其他设置的 flag 不会受到影响。
FULLSCREEN
虽然写的是 Fullscreen ,但其实只是隐藏 StatusBar。
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDecorView = getWindow().getDecorView(); mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN); // Google 建议隐藏 StatusBar 时也将 ActionBar 一起隐藏 getActionBar().hide();}
看图可以得出以下几点:
- 点击屏幕 StatusBar 不会显示出来
- 从屏幕上边缘往下滑可以让 StatusBar 重新显示
- 点击 home / 多任务键再返回 App 时 StatusBar 重新显示了出来,印证了超前提示里所说的。而且 StatusBar 在显示出来以后不会自动隐藏,这一点跟在 4.1 之前设置的全屏方式不一样,因为设置的 FULLSCREEN flag 已经被清除了,如果想重新隐藏,需要重新设置该 flag。
- StatusBar 的显示 / 隐藏会使 ImageView 大小发生了变化
为了防止布局大小不会因为 StatusBar 的显示 / 隐藏发生变化,有两种 flag 可供选择:
1.LAYOUT_STABLE
mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
这里有一点需要注意:设置多个标志位时要用 | 连接起来,不能多次调用 setSystemUiVisibility。如:
mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);mDecorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
这样的结果就是只有最后一次设置的 flag 生效,而之前设置的标志位会被清除。也就是说上面的代码中只设置了 LAYOUT_STABLE 而 FULLSCREEN 被清除了。所以如果想清除之前设置的所有 flag ,mDecorView.setSystemUiVisibility(0) 就可以了
这次布局并没有延伸到 StatusBar 底下,所以大小也就不会受到它的影响
2.LAYOUT_FULLSCREEN
mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
HIDE_NAVIGATION
protected void onCreate(Bundle savedInstanceState) { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);}
Google 建议隐藏 NavigationBar 的同时将 StatusBar 一起隐藏。
与隐藏 StatusBar 时不同的是,隐藏了 NavigationBar 以后,点击屏幕的任何位置都会导致设置的所有控制 SystemBar 相关的 flag 被清除,所以 SystemBar 重新显示了出来。这里还需要注意的在这种模式下点击屏幕点击事件会被屏蔽,要等到 SystemBar 显示出来以后再次点击,事件才会传递到我们的布局中。
与 LAYOUT_FULLSCREEN 类似的是, LAYOUT_HIDE_NAVIGATION 可以让布局内容延伸到 NavigationBar 的底部。
因为离开 App 后控制 SystemBar 相关的 flag 会被清除,所以可以按需在
onResume()
或者
onWindowFocusChanged()
中重新设置它们。
LOW_PROFILE
protected void onCreate(Bundle savedInstance) { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LOW_PROFILE);}
这种模式好像用的不多,作用是减少 StatusBar 中的图标并使其变暗,将 NavigationBar 中的按钮减弱成 3 个点。
直接上图来说明该 flag 的效果吧:
IMMERSIVE
需要配合 View.SYSTEM_UI_FLAG_FULLSCREEN 和 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 一起设置
mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE);
可以看到设置了该 flag 以后,点击屏幕不会让 SystemBar 显示出来。而在呼出 SystemBar 后,控制 SystemBar 相关的 flag 依然会被清除。
IMMERSIVE_STICKY
跟 IMMERSIVE 不同的是,在该模式下呼出的 SystemBar 会在短暂的显示后自动重新隐藏。在 SystemBar 显示出来的时候点击屏幕中心会立刻让 SystemBar 重新隐藏。所以在模式下不会清除控制 SystemBar 相关的 flag。但是离开 App 时还是会被清除。
所以在回到 App 的时候要重新激活它:
@Overridepublic void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}}
监听 SystemBar 的变化
通常情况下我们需要能够控制 SystemBar 的显示与隐藏,所以就需要监听 SystemBar 的状态。
protected void onCreate(Bundle savedInstance) { mDecorView.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { if (visibility == 0) { // SystemBar 处于显示状态 } else { // SystemBar 处于隐藏状态 } }});
- FULLSCREEN(4)
- HIDE_NAVIGATION(2)
- LOW_PROFILE(1)
括号中的数字是它们的值,现在让我们回到代码中。
onSystemUiVisibilityChange(int visibility) 中的 visibility 表示的是 LOW_PROFILE、FULLSCREEN 跟 HIDE_NAVIGATION 这三个值的和。
因为只有这 3 个值是跟控制 SystemBar 相关的。也就是说从 visibility
的值就可以只知道我们设置了哪些 flag。比如如果 visibility
为 4,说明设置了 FULLSCREEN;如果 visibility
为 7 则说明 3 种 flag 都设置了。所以当 visibility
为 0 时表示没有设置任何控制 SystemBar 的 flag,也就说明了 SystemBar 处于显示状态。为什么 visibility
的值会是它们三个的和呢?因为我们在设置 flag 的时候是用 | 将多个 flag 连接在一起的, | 就相当于把它们的值加起来。
当 SystemBar 显示或者隐藏的时候,该监听器就会被触发。但是如果使用的是 IMMERSIVE_STICKY ,在 SystemBar 被呼出的时候不会触发该监听器。
下面给出一个 Demo ,功能是点击图片时进入/退出全屏
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; @BindView(R.id.image) ImageView mImage; View mDecorView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); mDecorView = getWindow().getDecorView(); // 让图片铺满屏幕 mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } @OnClick(R.id.image) public void onClick() { // 只需要处理隐藏 SystemBar 就行了,因为显示 SystemBar 是由系统完成的 hideSystemUI(); } private void hideSystemUI() { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN); } private void showSystemUI() { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); }}
这里有一个问题,如果点击稍微快一点的话就会出现只隐藏 StatusBar 而没有隐藏 NavigationBar 的情况。如果有哪个小伙伴知道的话请告知一下。
希望这篇文章能给大家带来一点点帮助。
- Activity 全屏,沉浸式模式这一篇就够了
- Activity 全屏,沉浸式模式这一篇就够了
- 关于Activity,看这一篇就够了
- Activity 全屏,沉浸式模式(转)
- HTML基础,这一篇就够了
- css基础,这一篇就够了
- 线程池,这一篇就够了!
- 线程池这一篇就够了
- Activity、View、Window的理解一篇文章就够了
- 一篇就够了系列之Activity全解析
- Activity、View、Window的理解一篇文章就够了
- 23种设计模式全解析-- 设计模式看这一篇就够了
- 23种设计模式全解析--设计模式看这一篇就够了
- 深入浅出RxJava就这一篇就够了
- RxJava源码深度解析-就这一篇就够了
- Java 中的单例模式,看完这一篇就够了
- awk经典,有这一篇就够了
- [转]awk经典,有这一篇就够了
- 谁调用DllMain
- mysql数据备份
- 产品经理需要掌握的十大知识模块
- python和java的区别(python内存管理)
- ssm框架利用timer类创建定时任务
- Activity 全屏,沉浸式模式这一篇就够了
- Difference Between FTP and TFTP
- 关于 mac 下轻松 反编译安卓apk
- Swift3.0 代理传值,属性传值
- OpenCV与matlab部分函数的对应关系
- 简述cookies和session的区别
- Android 系统字体大小影响UI显示问题
- C++判断ip是否为保留ip
- JFace中Dialog类的使用方法