2

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

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

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

层次结构中的顶部视图覆盖onApplyWindowsInsets(). 实现只是记录WindowInsets它被传递的信息,然后调用超类方法,记录结果并返回它——没有任何修改。日志还显示超类方法没有修改插图。

现在我得到了一个看起来很奇怪的顶部插图,它似乎总是比我预期的多 56-72 dp:

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(),这里只报告最后一次。

视图实际上并没有超出可见的顶部:如果我在视图顶部绘制一个 24 像素的区域,它会出现在可见区域的顶部(即,如果有,则在状态栏下方),从不离屏。

如果我要信任这些插入值并按指示的像素数偏移内容以使其远离系统栏,我最终会在视图顶部出现间隙。

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

我该如何纠正?我忽略了什么吗?

4

1 回答 1

1

由于我仍然对报告的值没有任何解释,我认为这要么是一个错误,要么是一个记录不充分的功能,但它仍然存在于许多(如果不是全部)版本的 Android 中。

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

  • 存储传递给 的插图onApplyWindowsInsets(),仅丢弃顶部的插图。
  • 覆盖onSizeChanged()视图,并在其中调用View#getRootWindowInsets()以获取顶部插图(忽略其他插图)。

综合价值观对我有用。

不幸的是,这不适用于 API 20–22,它没有实现View#getRootWindowInsets(). 在这里,您需要做一些猜测。幸运的是,这更容易,因为这些 API 还没有实现分屏 - 顶部插图将是状态栏的高度,除非您明确要求将其隐藏(在这种情况下为 0)。如果状态栏是可见的,它的高度可以确定如下:

Resources resources = view.getResources();
int shid = resources.getIdentifier("status_bar_height", "dimen", "android");
padding_top = (shid > 0) ? resources.getDimensionPixelSize(shid) : 0;
于 2019-02-07T23:13:59.877 回答