应该会有人觉得百度(google)有的东西为什么我会写出来?有我还写啥啊~
手上有一个项目,是用cordova+vue的,这个不是重点,由于ios的app上架比较困难,所以优先上架android。
因为习惯了在ios上透明状态栏的样式,在android上也想拥有。得赖于ios的css中safe-area-inset-*的属性,可以在cordova的ios端结合cordova-plugin-statusbar插件实现透明状态栏,并且在顶部(或者底部,根据需要),让出安全距离,避免被顶部状态栏文字和底部横线挡住,于是心想在安卓也可以吧~
可以我就不写这篇了!!!!
预期效果如图
首先,贸然使用safe-area-inset-*在安卓上会出现2大问题!
1、没效果!
cordova-plugin-statusbar插件已经可以使得状态栏变得透明,且根据需要变换字体颜色?然而本该出现安全距离却没有也就是默认0?
值得注意的是,在我大量测试后发现,单独通过一句透明化状态栏的代码去实现是不可以的,我不知道是不是我的用法不对,还是确实是这样。这里我用了3句代码才实现了透明化。放代码!!
StatusBar.show(); StatusBar.overlaysWebView(false); StatusBar.overlaysWebView(true);
经过查看相关文档发现,该属性是ios独有的。
2、不兼容部分内核导致样式出错
没效果是最好的情况,我在同事的uc浏览器,无论手机版还是pc版都出现了由于不兼容safe-area-inset-*属性导致整个样式无法被渲染,出现了验证的样式bug,其实本该默认这个值为0的,却在部分内核下无法被识别。
推测,应该是使用了较低版本的内核导致的问题,所以出现了这个问题。
综上:解决问题迫在眉睫;
我们先解决第二个问题;
因为在本项目css中使用大量的calc方法,大胆推测var方法定义是没问题的。小范围实现证实想法!
:root是根结点也就是html,我们需要在里面重新定义safe-area-inset-*值!
值得一提的是,ios11于ios12使用safe-area-inset-*的方法是不一样的
ios11及以下使用constant(safe-area-inset-*)
ios12使用env(safe-area-inset-*)
在考虑用户群体可能使用ios11的情况下,必须统一,于是css兼容代码就诞生了
:root { --safe-area-inset-top: 0px; --safe-area-inset-right: 0px; --safe-area-inset-bottom: 0px; --safe-area-inset-left: 0px; @supports (top: constant(safe-area-inset-top)) { --safe-area-inset-top: constant(safe-area-inset-top); --safe-area-inset-right: constant(safe-area-inset-right); --safe-area-inset-bottom: constant(safe-area-inset-bottom); --safe-area-inset-left: constant(safe-area-inset-left); } @supports (top: env(safe-area-inset-top)) { --safe-area-inset-top: env(safe-area-inset-top); --safe-area-inset-right: env(safe-area-inset-right); --safe-area-inset-bottom: env(safe-area-inset-bottom); --safe-area-inset-left: env(safe-area-inset-left); } }
通过supports探针我们对把支持safe-area-inset-*赋予--safe-area-inset-*,对不支持的,一律赋值0px!!!
谨记,这里不能写0,必须是完整的0px;否则可能无效
最后,在凡是用到safe-area-inset-*的地方,改写为var(--safe-area-inset-*)
例如
div{ top:calc(44px - var(--safe-area-inset-top)); }
解决第二个问题了
回头我们攻克第一个问题
其实第二个问题网上有,只是没这么详细,第一个问题,也不必强求解决,但是对于喜欢研究的程序员来说,是一个研究的机会。
要解决第一个问题,必须基于第二个问题的基础上。
我们用的cordova-plugin-statusbar插件是不支持获取状态栏高度的,这就是为什么需要用css让出安全距离的一个原因。
假如,我们可以通过js获取到状态栏高度,利用第二个问题的css,动态拼接初始值动态写入html中,由于vue是单页应用,所以只要要写入一次,对所有的页面都必定是有效的。
要想获得状态栏高度,必须改写安卓代码,方法有2个
1、我用的是腾讯的X5内核,去改写其webview代码,在获取状态栏高度后,通过css注入到webview中!!研究了一个早上太过于硬核,放弃!
2、修改cordova-plugin-statusbar,使得我们可以用js去获取状态栏高度
放出代码,语法就不说了,需要会写安卓的人,我也是各自尝试再写出来的!
找到这个java文件,并写入代码
if ("getStatusBarHeight".equals(action)) { int result = 0; try { DisplayMetrics dm = new DisplayMetrics(); dm = cordova.getActivity().getResources().getDisplayMetrics(); float density = dm.density; int resourceId = cordova.getActivity().getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = cordova.getActivity().getResources().getDimensionPixelSize(resourceId); } Log.i("getStatusBarHeight", String.valueOf(result / density)); callbackContext.success(String.valueOf((result / density))); } catch (Exception e) { callbackContext.error("error"); } }
调试输出的语句大可去掉就好。找到对应的js文件
加入
getStatusBarHeight:function(success, error){ exec(success, error,'StatusBar','getStatusBarHeight',[]) },
在vue入口文件main.ts(或者main.js)中的监听deviceReady中加入ts(js)代码
StatusBar.getStatusBarHeight((height: string) => { if (Number(height) > 0) { //一些错误规避 //StatusBar.show(); //StatusBar.overlaysWebView(false); //StatusBar.overlaysWebView(true); const code: string = `:root{--safe-area-inset-top:${height}px;--safe-area-inset-right:0px;--safe-area-inset-bottom:0px;--safe-area-inset-left:0px;` + `@supports(top:constant(safe-area-inset-top)){--safe-area-inset-top:constant(safe-area-inset-top);--safe-area-inset-right:constant(safe-area-inset-right);` + `--safe-area-inset-bottom:constant(safe-area-inset-bottom);--safe-area-inset-left:constant(safe-area-inset-left)}` + `@supports(top:env(safe-area-inset-top)){--safe-area-inset-top:env(safe-area-inset-top);--safe-area-inset-right:env(safe-area-inset-right);` + `--safe-area-inset-bottom:env(safe-area-inset-bottom);--safe-area-inset-left:env(safe-area-inset-left)}}`; const style: any = document.createElement('style'); style.type = 'text/css'; style.rel = 'stylesheet'; style.appendChild(document.createTextNode(code)); const head: any = document.getElementsByTagName('head')[0]; head.appendChild(style); StatusBar.styleDefault(); } else { StatusBar.show(); }
然后编译,测试,微调,完美解决!!
发布于 2021-01-21 17:25:49 回复
发布于 2024-02-07 15:18:31 回复
网站制作
搬家公司
发布于 2024-02-07 15:19:06 回复
发布于 2024-07-24 12:57:45 回复
发布于 2024-07-24 22:32:08 回复
发布于 2024-07-24 22:32:45 回复
发布于 2024-08-15 20:59:56 回复
发布于 2024-08-15 21:27:13 回复
发布于 2024-08-16 19:29:26 回复
发布于 2024-08-16 19:30:18 回复
发布于 2024-08-16 20:23:21 回复
发布于 2024-08-17 16:59:25 回复