【发布时间】:2020-04-17 12:54:17
【问题描述】:
我在全屏 Java 应用程序中遇到了 getDisplayCutout() 问题。
我似乎只能在 onAttachedToWindow 函数中获得 DisplayCutout 的值。该功能完成后,我再也无法获得它。
获取抠图的代码:
WindowInsets insets = myActivity.getWindow().getDecorView().getRootWindowInsets();
if (insets != null) {
DisplayCutout displayCutout = insets.getDisplayCutout();
if (displayCutout != null && displayCutout.getBoundingRects().size() > 0) {
// we have cutouts to deal with
}
}
问题
一旦附加到视图层次结构,我如何才能在任何时间从代码中的任何位置可靠地获取显示切口?
重现问题
经过大量调查,我已将其范围缩小为全屏应用程序的一个非常广泛的问题,我很惊讶没有其他人询问它。 实际上,我们可以忽略我的应用程序,只需处理两个您现在可以自己制作的模板项目。
在 Android 工作室中,我谈论的是名为“基本活动”和“全屏活动”的手机和平板电脑项目。 如果您分别创建一个,并进行以下更改:
对于 Basic,通过在 Activity 标记下添加 android:configChanges="orientation|keyboardHidden|screenSize" 来更改 Manifest 以自行处理配置更改,如下所示:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/AppTheme.NoActionBar">
现在对于他们两个,将以下两个函数添加到活动文件中:
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
if (insets != null) {
DisplayCutout displayCutout = insets.getDisplayCutout();
if (displayCutout != null && displayCutout.getBoundingRects().size() > 0) {
// we have cutouts to deal with
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
WindowInsets insets = getWindow().getDecorView().getRootWindowInsets();
if (insets != null) {
DisplayCutout displayCutout = insets.getDisplayCutout();
if (displayCutout != null && displayCutout.getBoundingRects().size() > 0) {
// we have cutouts to deal with
}
}
}
这就是重现此问题所需要做的一切。 我在 API Q 上的 Pixel 3 模拟器上运行它,在该模拟器上我启用了模拟切口并选择了 BOTH(所以底部和顶部都有一个切口)
现在,如果您在我们尝试获取显示切口 (DisplayCutout displayCutout = insets.getDisplayCutout();) 的行上设置断点,您会在 Basic 应用上看到它在启动时运行和,当您更改方向时,但在全屏应用中,它仅在启动时有效。
事实上,在我的应用程序中,我使用onAttachedToWindow 中的以下代码进行了测试:
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
// start a thread so that UI thread execution can continue
WorkerThreadManager.StartWork(new WorkerCallback() {
@Override
public void StartWorkSafe() {
// run the following code on the UI thread
XPlatUtil.RunOnUiThread(new SafeRunnable() {
public synchronized void RunSafe() {
WindowInsets insets = myActivity.getWindow().getDecorView().getRootWindowInsets();
if (insets != null) {
DisplayCutout displayCutout = insets.getDisplayCutout();
if (displayCutout != null && displayCutout.getBoundingRects().size() > 0) {
// we have cutouts to deal with
}
}
}
});
}
});
}
此代码启动一个线程,以便 onAttachedToWindow 函数可以完成运行;但线程会立即将执行发送回 UI 线程以检查切口。
onAttachedToWindow 函数完成执行与我的代码检查 displayCutout 之间的延迟必须在纳秒级,但切口立即不可用。
有什么想法吗?这在某种程度上是预期的吗?
在方向改变时无法访问切口,我别无选择,只能记录最大的插图(纵向的顶部或底部,因为长边不能有它们),并将其应用于纵向的顶部和底部,或者左右横屏。
这是因为我无法在 android 中找到一种方法来检查当前处于活动状态的哪种景观(例如左侧或右侧的手机顶部)。 如果我能检查一下,我至少可以只在手机边缘需要它的地方应用插图。
【问题讨论】:
-
这就是为什么我有这个错误stackoverflow.com/questions/65620959/…这太烦人了!
标签: java android null fullscreen display-cutouts