用奇怪的顶部插入调用onApplyWindowInsets

时间:2019-02-06 16:41:05

标签: android android-layout windowinsets

我有一个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像素的区域,它会出现在可见区域的顶部(即,如果有的话,在状态栏下方)一个),永远不会在屏幕外显示。

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

合并的值对我有用。

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

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