android:fitsSystemWindows="true"没写的时候库内部运行了什么逻辑来适配导航栏,这个逻辑会出现bug吗?
SelectSex opened this issue · comments
- 系统版本(必须)/ Redmi 6 Android8.0.1
- 库版本(必须)/最新版
问题描述:
当配置了透明导航栏后:
<item name="android:windowTranslucentNavigation">true</item>
,app使用弹窗就是最简单的继承了Basepopwindow,在大部分手机上都可以让弹窗的底部在导航栏之上。
但是在Redmi 6 Android8.0.1上却导航栏覆盖了弹窗底部,刚好弹窗底部有个按钮需要点击,导致无法点击。
于是我加上了android:fitsSystemWindows="true",在Redmi 6 Android8.0.1上显示正常了,但是在其他手机上却
弹窗底部升高了两个 导航栏高度,
所以,这段逻辑里面,是弹窗内部的那个逻辑完成了自动适配导航栏,又为何在 Redmi 6 Android8.0.1上自动适配失效,这个是个值得讨论的问题
不设置透明导航栏
研究了一下午,有补了些沉浸式的知识,最后吧项目中的android:windowTranslucentNavigation">true去掉了,先解决问题再说
现有疑问如下,
我手上的其他手机,运行app后,因为设置了透明导航栏,所以加上了android:fitsSystemWindows="true",来让内容区下面抬升适应导航栏,顶部下移适应状态栏,然后启动了弹窗,弹窗检测到主题中的透明状态栏,所以,弹窗在Redmi 6 Android8.0.1上正确的将弹窗置于导航栏下方,但是其他的手机(我身边的其他手机)点击弹出弹窗后,没有根据activity的主题设置,正确的将弹窗置于导航栏上,而是根本没有检测到透明导航栏属性,默认就是弹窗在导航栏上方,直到今天发现Redmi 6 Android8.0.1准确的得到了透明导航栏指令,并将弹窗内容置于导航栏下,就发生了我今天提出的bug,两个手机,同样的设置却有了两种效果,我再两种效果间必须做出新的抉择,这里我也发现了android:fitsSystemWindows在正常activity和 popwindow的些许不同,比如activity默认都是全屏使用的我们通常会发现activity肯定是和状态栏有覆盖一说,所以加上android:fitsSystemWindows回自动设置状态栏适配,和导航栏适配,但是当我把android:fitsSystemWindows用在popwindow中后,不论弹窗内容区是否是全屏显示的,都会默认适配状态栏,比如我弹窗内容区只有屏幕3分之一,底部弹出,设置了透明导航栏后,我需要加上android:fitsSystemWindows来适配,回自动同时视频顶部,在内容区顶部产生和状态栏高度一样的padding,如果我内容区域有底色,就会看到仅仅只有3分之一屏幕弹窗却顶部和底部都有个适配区域,所以我只能放弃android:fitsSystemWindows适配,而是使用手动修改上下padding,
popup适配navigationbar是通过找decor下的id是否匹配navigationbackground的。
所以你可以layoutinspector查一下~
这个问题我下周再跟进,感谢提供这么详细的信息^o^
相关代码在PopupUiUtil下,方法名getNavigationBarBounds。
本周末我在外面,手机码字挺心塞的………
下周我会跟进的
根据上面评论的疑问,我调试代码跟踪Redmi 6 Android8.0.1在运行查找导航view的方法代码发现,设置透明导航栏以后,
PopupUiUtils. getNavigationBarBounds方法的代码
for (int i = 0, count = decorView.getChildCount(); i < count; i++) {
final View child = decorView.getChildAt(i);
final int id = child.getId();
if (id != View.NO_ID) {
String resourceEntryName = getResNameById(id);
if ("navigationBarBackground".equals(resourceEntryName)
&& child.getVisibility() == View.VISIBLE) {
isVisible = true;
break;
}
}
}
及时Redmi 6 Android8.0.1手机状态栏是显示的,因为透明,所以以上for循环得到的导航栏view是空,调试完我就感觉拿到,当导航栏有颜色的时候,以上for循环才可以得到导航view,在非Redmi 6 Android8.0.1手机上即使设置了透明导航栏,上面for循环是可以得到导航栏view的。到这里问题基本上就清楚了,
Redmi 6 Android8.0.1手机有bug,当设置导航栏透明沉浸式后,导航栏显示,但是上面的for循环代码是找不到导航view的,
正在跟进,差不多就是如此,除了Redmi 6 Android8.0.1这个手机的自身bug导致获取导航栏view 的代码失效的问题外,就是
android:fitsSystemWindows在弹窗中的表现不尽人意,希望可以作者自己个PopupDecorViewProxy加入个调用就可以设置兼容上下导航栏和状态栏适配的方法,
还有弱弱的问下,弹窗中有recyclerview,recyclerview中有edittext,然后键盘的弹出的相关还能优化下不,
算了,键盘问题是个老大难,恶心的一批,最后我自定义数字键盘先用着了,键盘随着焦点丢失自动从数字键盘变成字母键盘,高度抖一抖,滑动列表回来获取焦点后,有从字母键盘变成数字键盘,还有就是键盘弹出延时300ms还能弹出,但是我想设置尽快弹出,就改为100ms,或者更短,就容易无法自动弹出键盘成功,键盘问题真是恼火,需要的知识点和兼容性知识也比较真是让人头大
大佬也别急,问题慢慢处理,手机码字辛苦了,哈哈
recycle键盘相关的文档有,可以去看看
研究了一下午,有补了些沉浸式的知识,最后吧项目中的android:windowTranslucentNavigation">true去掉了,先解决问题再说
现有疑问如下, 我手上的其他手机,运行app后,因为设置了透明导航栏,所以加上了android:fitsSystemWindows="true",来让内容区下面抬升适应导航栏,顶部下移适应状态栏,然后启动了弹窗,弹窗检测到主题中的透明状态栏,所以,弹窗在Redmi 6 Android8.0.1上正确的将弹窗置于导航栏下方,但是其他的手机(我身边的其他手机)点击弹出弹窗后,没有根据activity的主题设置,正确的将弹窗置于导航栏上,而是根本没有检测到透明导航栏属性,默认就是弹窗在导航栏上方,直到今天发现Redmi 6 Android8.0.1准确的得到了透明导航栏指令,并将弹窗内容置于导航栏下,就发生了我今天提出的bug,两个手机,同样的设置却有了两种效果,我再两种效果间必须做出新的抉择,这里我也发现了android:fitsSystemWindows在正常activity和 popwindow的些许不同,比如activity默认都是全屏使用的我们通常会发现activity肯定是和状态栏有覆盖一说,所以加上android:fitsSystemWindows回自动设置状态栏适配,和导航栏适配,但是当我把android:fitsSystemWindows用在popwindow中后,不论弹窗内容区是否是全屏显示的,都会默认适配状态栏,比如我弹窗内容区只有屏幕3分之一,底部弹出,设置了透明导航栏后,我需要加上android:fitsSystemWindows来适配,回自动同时视频顶部,在内容区顶部产生和状态栏高度一样的padding,如果我内容区域有底色,就会看到仅仅只有3分之一屏幕弹窗却顶部和底部都有个适配区域,所以我只能放弃android:fitsSystemWindows适配,而是使用手动修改上下padding,
注意:android:fitsSystemWindows 在大部分手机上都是半屏弹窗自动加顶部padding和底部padding,但是就是Redmi 6 Android8.0.1上设置弹窗根布局 android:fitsSystemWindows=true无效,应该和android:windowTranslucentNavigation">true,有关,
为啥在此续写注意事项:因为今天我继续想找个完美方案,最后找到了 ViewCompat.setOnApplyWindowInsetsListener方法上,然后今天用这个问题手机在弹窗根布局设置了android:fitsSystemWindows=true,突然发现不会自动加上下padding,我以为昨天发布的android:fitsSystemWindows自动加上下布局的问题反馈是我提错了,,折腾了好几十分钟都无法自动加上下padding,突然才恍然大悟,可能是这个手机的问题,换个正常手机就可以使用android:fitsSystemWindows=true了,
现在手上这个Redmi 6 Android8.0.1这种奇怪的bug我用另一个,Redmi 6 Android 9,也复现了,也是神奇,就这个机型有问题。。。,
可以运行下layoutinspector,把li文件导出来分享到git评论这里吗?
我快到家了,可以研究一下
可以
或者加下我微信razerdp
今天一直在研究可以,自己实现 fitsSystemWindows的测量导航栏高度的代码,找到了
ViewCompat.setOnApplyWindowInsetsListener
方法,但是这个知识基础太薄弱,英语也不太好,棘手呀,就希望大佬可以实现 测量 导航栏高度的代码,
我就可以在app】设置了透明导航栏的情况,给所有弹窗,设置
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
让弹窗也显示在导航栏下面,然后用 我们自己的 fitsSystemWindows的测量代码,手动padding,差不多就可以解决现在已有的问题了
注:手上的问题手机和正常手机在 弹窗主动设置了
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
后都是效果一致,弹窗在导航栏下方,在此一致的情况我才想着手动设置导航栏高度padding,苦于小白条,虚拟导航栏,等等高度都不一致。就发现 fitsSystemWindows 的测量导航栏高度的逻辑很强大,基本上手上的手机,activity设置了 fitsSystemWindows。都是准确测量导航栏高度了,
as 4.0之后导出li文件稍微有点小复杂~
shift 两次,然后键入 legacy layout inspector,捕捉后,在项目的captrues下有li文件
OnApplyWindowInsetsListener在解决navigationbar之前其实看到过了,但这货在api 21以上才有效,我们BasePopup最低支持16。。。被限制住了。。
razerdp.basepopup_2021.10.31_16.40-1.zip
我项目最低21,要不先把这个功能搞起来,19的手机我都不适配了。。。。
噗,我不可能为了你把通用库改掉的。。。。我的库使用者还存在4.x的人的说
另外你的li我需要decorview的,popup的可以不用。
li文件的信息也太少了,还只能截取一层窗口,截取的图上连导航栏都看不到,
activity的截取razerdp.basepopup_2021.10.31_16.44.zip
我说你可以加上功能,然后告知,仅支持21以上,哈哈,大部分都用户先满足了
噗,不可以随便加的~
得先找到原理嘛= =
不过确实navigationbar都没了,估计是这台红米的ROOM做过奇怪的处理,如果navigationbar都找不到,那么库会理所当然的认为没有导航栏了。。。
加我微信吧,我们微信聊
或者这个功能写成一个工具类,放在demo中,可以开发者自己调用,关键是这个东西我写的有点吃力,经验有不足,写不好。
微信等晚上吧,我手机今天没带到公司,走的急加班中
关键是,fitsSystemWindows在activity中表现正常,弹窗就无效了在这个红米6上,坑死了,我现在只能先写死加上padding了,我项目默认是透明导航栏的,加上总是对的
话说,为啥要在弹窗中加fitsystemwindow
估计是特定机型的问题了
话说,为啥要在弹窗中加fitsystemwindow
这个红米6上,弹窗底部在导航栏下显示,就是我上面给你截的图,我项目弹窗底部是有提交按钮的。导航栏盖住,我就没法点击按钮了,要么自己加padding要么使用fitsSystemWindows,但是fitsSystemWindows 竟然是无效的。。。。
可以,我去研究一下
可以,我去研究一下
哈哈哈,你复现了,看来解决问题的时候不远了,开心
可以,我去研究一下
注意这个bug手机的activiyt是可以正常使用fitsSystemWindows,得到这个假的导航栏的高度的,这就很屌了
初步修复了一下,请更新到3.2.1-SNAPSHOT
当前修复方案简述如下:通过WindowInsets二次判断
详述如下:
ProxyView增加insets监听:
PopupHelper增加二次Nav确认:
牛逼,一个方法就完成了,效果很好,就像默认就用上了fitsystemwindos一样,需要弹窗沉入导航栏只需要
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
即可,nice