沉浸式状态栏4.4及5.0以上通用
来源:互联网 发布:马蓉 知乎 编辑:程序博客网 时间:2024/05/31 19:54
Android从4.4开始有沉浸式状态栏效果,5.0以前的实现很简单:
如果手机版本大于等于4.4,就实现沉浸式状态栏效果:
//4.4版本及以上if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { window.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);}但是5.0及其以上的,还是有个小蓝条在最上面,没有达到沉浸式状态栏效果,对于5.0及其以上系统的解决办法:
//5.0版本及以上if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.BLACK);}
综上,可以写个基类,让其他activity继承此基类即可:
public class BaseActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); immersiveStatusBar(); } private void immersiveStatusBar() { Window window = getWindow(); //4.4版本及以上 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { window.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } //5.0版本及以上 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.BLACK); } if (AndroidWorkaround.checkDeviceHasNavigationBar(this)) { AndroidWorkaround.assistActivity(findViewById(android.R.id.content)); } }}
这样,所有系统均可适配沉浸式状态栏了。
注:使用沉浸式状态栏后,有的华为手机下面的虚拟按键会把项目的底部导航(如果有的话)给遮盖,解决办法:
一、概述
在项目中,测试发现在一些华为手机的屏幕适配上出现了问题,主要是因为华为Mate等一些系列的手机有一个虚拟按键的设计.当这些虚拟按键由用户手势滑出,或默认显示的话,就会遮挡我们本身的应用布局.比如欢迎界面过后是四个Fragment,那么底部的四个tab就会被虚拟的导航栏遮住,非常难看.
当然,欢迎页的图片适配也同样会出现问题.
Google后得出第一个问题的解决方案.第二个图片的问题则用自己摸索的方式解决,当然也非常简单.
二、布局由于虚拟按键导致导航栏顶上去的解决方法
在我们的项目中加载Fragment的MainActivity,以及其他一般的Activity继承的BaseActivity中的onCreate方法中添加如下代码:
if (AndroidWorkaround.checkDeviceHasNavigationBar(this)) { AndroidWorkaround.assistActivity(findViewById(android.R.id.content));}
其中AndroidWorkaround使我们为了解决该问题而封装的类,也可以看作是一个特定的工具类:
/*** 解决底部屏幕按键适配* Created by Mercury on 2016/10/25.*/public class AndroidWorkaround { public static void assistActivity(View content) { new AndroidWorkaround(content); } private View mChildOfContent; private int usableHeightPrevious; private ViewGroup.LayoutParams frameLayoutParams; private AndroidWorkaround(View content) { mChildOfContent = content; mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { frameLayoutParams.height = usableHeightNow; mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom); } public static boolean checkDeviceHasNavigationBar(Context context) { boolean hasNavigationBar = false; Resources rs = context.getResources(); int id = rs.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { hasNavigationBar = rs.getBoolean(id); } try { Class systemPropertiesClass = Class.forName("android.os.SystemProperties"); Method m = systemPropertiesClass.getMethod("get", String.class); String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys"); if ("1".equals(navBarOverride)) { hasNavigationBar = false; } else if ("0".equals(navBarOverride)) { hasNavigationBar = true; } } catch (Exception e) { } return hasNavigationBar; }}
重新测试,发现无论是否弹出虚拟按键,都不会再次遮挡tab按钮。
三、原理
上面的代码需要在setContentView后面执行。其最初的解决方案是stackoverflow上有人为了适配软键盘在全屏下的布局问题。
开始先判断该设备上是否存在导航栏。为什么用findViewById(Android.R.id.content)呢?因为android.R.id.content这个id代表的就是所在页面的根布局,而并不需要特别指定一个id给该布局。可以通过调用系统API返回的结果,也可以通过判断该手机是否为华为手机,操作系统属于哪种类型来来判断。
一旦确定该设备存在导航栏,将对该布局进行重新测量。首先mChildOfContent得到其视图树,对全局高度实现监听。
OnGlobalLayoutListener 是ViewTreeObserver的内部类,当一个视图树的布局发生改变时,可以被ViewTreeObserver监听到,这是一个注册监听视图树的观察者(observer),在视图树的全局事件改变时得到通知。ViewTreeObserver不能直接实例化,而是通过getViewTreeObserver()获得。
接着得到视图目前可用的总高度,将其赋值给mChildOfContent的布局高度。调用requestLayout,让mChildOfContent要求自己的parent view对自己重新设置位置。
四、全屏图片的适配
解决了布局的问题,再来看欢迎页启动时候全屏图片的适配问题。发现该方法对于图片不适用。如下图,当虚拟按键弹出时,图片照样被遮挡了底部的一小部分。
如果隐藏虚拟按键,图片大小恢复正常
仔细想想,对于一个ImageView直接占据一个layout的情况,是没有必要再去写一些代码进行适配的。到布局里一看,发现ImageView的属性 android:scaleType=”centerCrop”
将其改为 android:scaleType=”fitXY”就可以解决了。这样图片可能高度会随着虚拟键的弹出而压缩,但是很好的适配了布局高度的变化而不会被遮挡。
- 沉浸式状态栏4.4及5.0以上通用
- Android 沉浸式状态栏 支持4.4及以上。
- 完美兼容4.4及以上系统实现沉浸式状态栏
- Android 5.0及以上系统实现沉浸式状态栏
- 沉浸式状态栏(Android4.4及以上)
- 5.0以上沉浸式状态栏设置方式
- Android沉浸式状态栏的实现在4.4及以上的系统中
- 对系统版本为4.4及以上的开启 透明状态栏和导航栏(即沉浸式状态栏)
- Android之4.4版本以上沉浸式状态栏实现
- android 4.4以上可以实现的沉浸式状态栏效果
- MIUI 6 沉浸式状态栏(Android 4.4以上)
- 沉浸状态栏的实现(5.0以上方案)
- Android KITKAT 以上实现沉浸式状态栏
- Android KITKAT 以上实现沉浸式状态栏
- Android4.4以上沉浸式状态栏
- Android KITKAT 以上实现沉浸式状态栏
- Android KITKAT 以上实现沉浸式状态栏
- Android4.4以上实现沉浸式状态栏
- nyoj 1278 【二叉搜索树】 G: Prototypes analyze
- 前端之DOM,BOM
- 分布式配置管理平台XXL-CONF
- IO
- 《JavaFX应用程序添加HTML内容》-更新内容
- 沉浸式状态栏4.4及5.0以上通用
- 字符串处理://在母串中查找子串,只保留子串之后的数据
- 新的开始
- Linux系统进程间通讯-信号
- PAT+1017+A除以B
- static通俗演义
- 应用程序调试(二)————使用GDB来调试应用程序
- Android线程的创建与销毁
- RF中变量基础使用