调用onApplyWindowInsets具有奇怪的顶部插入 [英] onApplyWindowInsets called with strange top inset

查看:604
本文介绍了调用onApplyWindowInsets具有奇怪的顶部插入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Android应用,其主题具有以下设置:

I have an Android app which has the following settings in its theme:

<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>

<item name="android:windowDrawsSystemBarBackgrounds">true</item>

层次结构中的顶部视图将覆盖 onApplyWindowsInsets().该实现只记录它传递的 WindowInsets ,然后调用超类方法,记录结果并返回它-无需进行任何修改.日志还显示,超类方法不会修改插图.

The top View in the hierarchy overrides onApplyWindowsInsets(). The implementation just logs the WindowInsets it was passed, then calls through to the superclass method, logs the result and returns it—nothing is modified. The log also shows that the superclass method does not modify the insets.

现在我得到一个奇怪的顶部插图,看起来总是比我期望的要高出56-72 dp.

Now I am getting an odd-looking top inset, which always seems to be some 56–72 dp more than what I would expect it to be:

Platform           DPI    Layout                  Inset         Bar          Difference

Android x86_64 8.1 MDPI   Landscape               88 px/dp      24 px/dp     64 px/dp
                          Landscape, split        80 px/dp      24 px/dp     56 px/dp
Anbox              MDPI   Window                  64 px/dp      None         64 px/dp
LineageOS 15.1     XXHDPI Portrait                240 px/80 dp  72 px/24 dp  168 px/56 dp
                          Portrait, split/top     216 px/73 dp  72 px/24 dp  144 px/48 dp
                          Portrait, split/bottom  144 px/48 dp  None         144 px/48 dp
SDK Emulator (6.0) HDPI   Portrait                120 px/80 dp  36 px/24 dp  84 px/56 dp

注意:在横向模式下,有两个连续的 onApplyWindowInsets()调用,此处仅报告最后一个.

Note: in landscape mode, there are two consecutive calls to onApplyWindowInsets(), only the last ones are reported here.

该视图实际上并没有超出可见范围的顶部:如果我在视图顶部绘制一个24像素的区域,它将显示在可见区域的顶部(即,如果有的话,则位于状态栏的下方)一个),永远不会在屏幕外显示.

The view is not actually extended beyond the top of what is visible: If I draw a 24-px area at the top of my view, it appears at the top of the visible area (i.e. underneath the status bar if there is one), never off-screen.

如果我相信这些插入值和偏移量所指示的像素数,以使其远离系统条,那么我将在视图顶部出现一个空白.

If I were to trust these inset values and offset content by the number of pixels indicated to keep it clear of the system bars, I would end up with a gap at the top of the view.

据我所知,左/右/底值似乎还可以.

Left/right/bottom values seem OK as far as I can tell.

我该如何纠正?我在俯视什么吗?

How can I correct this? Am I overlooking something?

推荐答案

由于我仍然无法解释所报告的值,因此我认为这要么是错误,要么是文献记载不充分的功能,尽管如此,它仍然存在于许多功能中(如果没有,所有)版本.

As I still have no explanation for the values reported, I assume this is either a bug or a poorly documented feature, which is nevertheless present in many (if not all) versions of Android.

幸运的是,至少在API 23+上,还有另一种获取窗口插图的方法,即调用 View#getWindow().getRootView().getRootWindowInsets().这似乎有本身有一些错误,即报告导航栏的插入不正确,但是将两个结果合并已奏效对我来说.

Luckily, at least on API 23+, there is another method to get window insets, namely by calling View#getWindow().getRootView().getRootWindowInsets(). This seems to have some bugs of its own, namely reporting incorrect insets for the navigation bar, but merging the two results has worked for me.

  • 存储传递给 onApplyWindowsInsets()的插图,仅丢弃最上面的一个.
  • 为视图覆盖 onSizeChanged(),并在其中调用 View#getRootWindowInsets()以获取顶部插图(忽略其他插图).
  • Store the insets passed to onApplyWindowsInsets(), discarding only the top one.
  • Override onSizeChanged() for the view, and in it call View#getRootWindowInsets() to get the top inset (ignore the others).

合并的值对我有用.

不幸的是,这不适用于API 20–22,该API无法实现 View#getRootWindowInsets().在这里,您将需要做一些猜测.幸运的是,这很容易,因为这些API尚未实现分屏显示-顶部插图将是状态栏的高度,除非您明确要求将其隐藏(在这种情况下为0).如果状态栏可见,则可以按以下方式确定其高度:

Unfortunately this will not work on API 20–22, which does not implement View#getRootWindowInsets(). Here, you will need to do some guesswork. Fortunately, this is easier as these APIs do not implement split screen yet—the top inset will be the height of the status bar, unless you’ve explicitly requested that it be hidden (in which case it is 0). If the status bar is visible, its height can be determined as follows:

Resources resources = view.getResources();
int shid = resources.getIdentifier("status_bar_height", "dimen", "android");
padding_top = (shid > 0) ? resources.getDimensionPixelSize(shid) : 0;

这篇关于调用onApplyWindowInsets具有奇怪的顶部插入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆