Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android:fitsSystemWindows="true"没写的时候库内部运行了什么逻辑来适配导航栏,这个逻辑会出现bug吗? #452

Closed
SelectSex opened this issue Oct 29, 2021 · 34 comments
Labels

Comments

@SelectSex
Copy link

SelectSex commented Oct 29, 2021

  • 系统版本(必须)/ Redmi 6 Android8.0.1
  • 库版本(必须)/最新版

问题描述:
当配置了透明导航栏后:
<item name="android:windowTranslucentNavigation">true</item>
image

,app使用弹窗就是最简单的继承了Basepopwindow,在大部分手机上都可以让弹窗的底部在导航栏之上。
但是在Redmi 6 Android8.0.1上却导航栏覆盖了弹窗底部,刚好弹窗底部有个按钮需要点击,导致无法点击。
于是我加上了android:fitsSystemWindows="true",在Redmi 6 Android8.0.1上显示正常了,但是在其他手机上却
弹窗底部升高了两个 导航栏高度,
所以,这段逻辑里面,是弹窗内部的那个逻辑完成了自动适配导航栏,又为何在 Redmi 6 Android8.0.1上自动适配失效,这个是个值得讨论的问题
不设置透明导航栏
image

设置透明导航栏
image

手机参数
image

@SelectSex
Copy link
Author

研究了一下午,有补了些沉浸式的知识,最后吧项目中的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,

@razerdp
Copy link
Owner

razerdp commented Oct 29, 2021

popup适配navigationbar是通过找decor下的id是否匹配navigationbackground的。

所以你可以layoutinspector查一下~

这个问题我下周再跟进,感谢提供这么详细的信息^o^

@razerdp
Copy link
Owner

razerdp commented Oct 29, 2021

相关代码在PopupUiUtil下,方法名getNavigationBarBounds。

本周末我在外面,手机码字挺心塞的………

下周我会跟进的

@SelectSex
Copy link
Author

根据上面评论的疑问,我调试代码跟踪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的,

@SelectSex
Copy link
Author

正在跟进,差不多就是如此,除了Redmi 6 Android8.0.1这个手机的自身bug导致获取导航栏view 的代码失效的问题外,就是
android:fitsSystemWindows在弹窗中的表现不尽人意,希望可以作者自己个PopupDecorViewProxy加入个调用就可以设置兼容上下导航栏和状态栏适配的方法,

还有弱弱的问下,弹窗中有recyclerview,recyclerview中有edittext,然后键盘的弹出的相关还能优化下不,
算了,键盘问题是个老大难,恶心的一批,最后我自定义数字键盘先用着了,键盘随着焦点丢失自动从数字键盘变成字母键盘,高度抖一抖,滑动列表回来获取焦点后,有从字母键盘变成数字键盘,还有就是键盘弹出延时300ms还能弹出,但是我想设置尽快弹出,就改为100ms,或者更短,就容易无法自动弹出键盘成功,键盘问题真是恼火,需要的知识点和兼容性知识也比较真是让人头大

大佬也别急,问题慢慢处理,手机码字辛苦了,哈哈

@SelectSex
Copy link
Author

还有于是我看了看其他获取导航栏的方式里面遇到各种问题
比如布兰科鸡写的工具类中提到的三星手机导航栏自身问题

image

这种兼容问题最是头疼了

@razerdp
Copy link
Owner

razerdp commented Oct 29, 2021

recycle键盘相关的文档有,可以去看看

@SelectSex
Copy link
Author

研究了一下午,有补了些沉浸式的知识,最后吧项目中的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,也复现了,也是神奇,就这个机型有问题。。。,

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

可以运行下layoutinspector,把li文件导出来分享到git评论这里吗?

我快到家了,可以研究一下

@SelectSex
Copy link
Author

可以

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

或者加下我微信razerdp

@SelectSex
Copy link
Author

image
studio如何导出li文件,这个我还真没导出过,研究了一下还是没找到导出按钮

@SelectSex
Copy link
Author

image
这是弹窗,加入了fitsSystemWindows

@SelectSex
Copy link
Author

今天一直在研究可以,自己实现 fitsSystemWindows的测量导航栏高度的代码,找到了
ViewCompat.setOnApplyWindowInsetsListener
方法,但是这个知识基础太薄弱,英语也不太好,棘手呀,就希望大佬可以实现 测量 导航栏高度的代码,

我就可以在app】设置了透明导航栏的情况,给所有弹窗,设置
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
让弹窗也显示在导航栏下面,然后用 我们自己的 fitsSystemWindows的测量代码,手动padding,差不多就可以解决现在已有的问题了

注:手上的问题手机和正常手机在 弹窗主动设置了
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
后都是效果一致,弹窗在导航栏下方,在此一致的情况我才想着手动设置导航栏高度padding,苦于小白条,虚拟导航栏,等等高度都不一致。就发现 fitsSystemWindows 的测量导航栏高度的逻辑很强大,基本上手上的手机,activity设置了 fitsSystemWindows。都是准确测量导航栏高度了,

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

as 4.0之后导出li文件稍微有点小复杂~

shift 两次,然后键入 legacy layout inspector,捕捉后,在项目的captrues下有li文件

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

OnApplyWindowInsetsListener在解决navigationbar之前其实看到过了,但这货在api 21以上才有效,我们BasePopup最低支持16。。。被限制住了。。

@SelectSex
Copy link
Author

razerdp.basepopup_2021.10.31_16.40-1.zip

我项目最低21,要不先把这个功能搞起来,19的手机我都不适配了。。。。

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

噗,我不可能为了你把通用库改掉的。。。。我的库使用者还存在4.x的人的说

另外你的li我需要decorview的,popup的可以不用。

@SelectSex
Copy link
Author

SelectSex commented Oct 31, 2021

li文件的信息也太少了,还只能截取一层窗口,截取的图上连导航栏都看不到,
image
activity的截取razerdp.basepopup_2021.10.31_16.44.zip

@SelectSex
Copy link
Author

我说你可以加上功能,然后告知,仅支持21以上,哈哈,大部分都用户先满足了

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

噗,不可以随便加的~

得先找到原理嘛= =

不过确实navigationbar都没了,估计是这台红米的ROOM做过奇怪的处理,如果navigationbar都找不到,那么库会理所当然的认为没有导航栏了。。。

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

加我微信吧,我们微信聊

@SelectSex
Copy link
Author

或者这个功能写成一个工具类,放在demo中,可以开发者自己调用,关键是这个东西我写的有点吃力,经验有不足,写不好。
微信等晚上吧,我手机今天没带到公司,走的急加班中

@SelectSex
Copy link
Author

关键是,fitsSystemWindows在activity中表现正常,弹窗就无效了在这个红米6上,坑死了,我现在只能先写死加上padding了,我项目默认是透明导航栏的,加上总是对的

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

话说,为啥要在弹窗中加fitsystemwindow

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

微信截图_20211031210034

我的红米平板试了一下,android 10,没啥问题,。

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

估计是特定机型的问题了

@SelectSex
Copy link
Author

话说,为啥要在弹窗中加fitsystemwindow

这个红米6上,弹窗底部在导航栏下显示,就是我上面给你截的图,我项目弹窗底部是有提交按钮的。导航栏盖住,我就没法点击按钮了,要么自己加padding要么使用fitsSystemWindows,但是fitsSystemWindows 竟然是无效的。。。。

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

emmm,我复现了,windowTranslucentNavigation的时候,navigationbar直接没了。

然而小米ROM给它加上了哈哈哈哈

而我用系统的原生模拟器,navigation没有去掉,只是没了background而已

ROM坑爹

微信截图_20211031210542

微信截图_20211031210715

@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

可以,我去研究一下

@SelectSex
Copy link
Author

可以,我去研究一下

哈哈哈,你复现了,看来解决问题的时候不远了,开心

@SelectSex
Copy link
Author

可以,我去研究一下

注意这个bug手机的activiyt是可以正常使用fitsSystemWindows,得到这个假的导航栏的高度的,这就很屌了

razerdp added a commit that referenced this issue Oct 31, 2021
修复navigationbar不在DecorView层级下的判断问题(通过WindowInsets二次判断),fixed bug [#452](#452)
@razerdp razerdp added the bug label Oct 31, 2021
@razerdp
Copy link
Owner

razerdp commented Oct 31, 2021

@SelectSex

初步修复了一下,请更新到3.2.1-SNAPSHOT

当前修复方案简述如下:通过WindowInsets二次判断

详述如下:

ProxyView增加insets监听:

https://github.com/razerdp/BasePopup/blob/dev/lib/src/main/java/razerdp/basepopup/PopupDecorViewProxy.java#L89

PopupHelper增加二次Nav确认:

https://github.com/razerdp/BasePopup/blob/dev/lib/src/main/java/razerdp/basepopup/BasePopupHelper.java#L570

@SelectSex SelectSex reopened this Oct 31, 2021
@SelectSex
Copy link
Author

牛逼,一个方法就完成了,效果很好,就像默认就用上了fitsystemwindos一样,需要弹窗沉入导航栏只需要
setOverlayNavigationBar(true)
setOverlayNavigationBarMode(BasePopupFlag.OVERLAY_CONTENT)
即可,nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants