7

我正在尝试获取 DisplayCutout 并获取

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法 'android.view.DisplayCutout android.view.WindowInsets.getDisplayCutout()'

这是我的代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
   DisplayCutout displayCutout;
   displayCutout = getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
   //Logger.e(TAG, "MARGIN " + displayCutout.getSafeInsetTop());
}
4

7 回答 7

4

你应该把你的代码放在

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
      DisplayCutout displayCutout;
      displayCutout = 
      getWindow().getDecorView().getRootWindowInsets().getDisplayCutout();
     //Logger.e(TAG, "MARGIN " + displayCutout.getSafeInsetTop());
    }
}
于 2019-06-05T15:22:42.867 回答
3

当且仅当视图被分离时,getRootWindowInsets 返回 null。确保您从正确的上下文中调用它。

于 2018-12-02T00:53:04.890 回答
1

我不得不使用OnApplyWindowInsetsListener和 get DisplayCutoutfrom的组合DecorView

public class MyActivity extends AppCompatActivity implements androidx.core.view.OnApplyWindowInsetsListener {

    private Rect insets = new Rect();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        //...
        ViewCompat.setOnApplyWindowInsetsListener(getWindow().getDecorView(), this);
    }

    @Override
    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
        DisplayCutoutCompat cutoutCompat = insets.getDisplayCutout();
        if (cutoutCompat != null) {
            this.insets.set(cutoutCompat.getSafeInsetLeft(), cutoutCompat.getSafeInsetTop(), cutoutCompat.getSafeInsetRight(), cutoutCompat.getSafeInsetBottom());
        } else {
            this.insets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
        }

        //cutoutCompat is null at this point... So get it the other way.
        if (getWindow().getDecorView() != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            WindowInsets rootWindowInsets = getWindow().getDecorView().getRootWindowInsets();
            if (rootWindowInsets != null) {
                DisplayCutout displayCutout = rootWindowInsets.getDisplayCutout();
                if (displayCutout != null) {
                    this.insets.set(displayCutout.getSafeInsetLeft(), displayCutout.getSafeInsetTop(), displayCutout.getSafeInsetRight(), displayCutout.getSafeInsetBottom());
                }
            }
        }

        return insets;
    }
}
于 2019-12-03T08:22:58.137 回答
1
public static boolean hasNotchInScreenOfAndroidP(View context) {
    final boolean[] ret = {false};
    final View view=context;
    if (Build.VERSION.SDK_INT >= 28) {
        if (context==null){
        }else {
            context.post(new Runnable() {
                @Override
                public void run() {
                    WindowInsets windowInsets=view.getRootWindowInsets();
                    if (windowInsets==null){
                    }else {
                        DisplayCutout displayCutout = view.getRootWindowInsets().getDisplayCutout();
                        if (displayCutout == null ) {
                            ret[0] = false;
                        } else {
                            List<Rect> rects = displayCutout.getBoundingRects();
                            if (rects == null || rects.size() == 0) {
                                ret[0] = false;
                            } else {
                                ret[0] = true;
                            }
                        }
                    }
                }
            });

        }

    }
    return ret[0];
}

ComUtil.getStateBarHeightOfSeparationFromTheTop(this, getWindow().getDecorView());

于 2019-08-02T09:51:06.073 回答
0

试试下面的代码。我能够使用View.OnAttachStateChangeListener获得状态栏高度。就我而言,我已将侦听器附加到 ScrollView(mDetailScrollView),将其更改为您想要附加侦听器的任何视图。

    ...
    mDetailScrollView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View v) {                
            DisplayCutout displayCutout = getDisplayCutout();
            if (displayCutout != null) {
                // your code...
            }
        }

        @Override
        public void onViewDetachedFromWindow(View v) {
        }
    });
    ...

    private DisplayCutout getDisplayCutout() {
        if (activity != null) {
            WindowInsets windowInsets = getWindow().getDecorView().getRootWindowInsets();
            if (windowInsets != null) {
                return windowInsets.getDisplayCutout();
            }
        }

        return null;
    }
于 2019-02-14T16:48:36.023 回答
0

你可以在处理程序中获得 DisplayCutout

    val cutoutHandler = HandlerThread("cutout-thread")
    cutoutHandler.start()
    var handler = object : Handler(cutoutHandler.looper) {
        override fun handleMessage(msg: Message?) {
            super.handleMessage(msg)
            runOnUiThread {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // 9.0原生
                    val windowInsets = window.decorView.rootWindowInsets
                    val displayCutout = windowInsets.displayCutout
                }
                cutoutHandler.quit()
            }
        }
    }
    Thread {
        handler.sendEmptyMessage(0)
    }.start()
于 2019-04-12T02:52:53.407 回答
0

这是在运行模拟器时发生在我身上的。看起来即使你有一个带有默认皮肤的模拟器,它有一个显示切口,它仍然可能不会将它注册为一个显示切口设备。

您可以通过在开发人员选项中启用“模拟带有切口的显示”来解决此问题:
https ://developer.android.com/guide/topics/display-cutout/#test_how_your_content_renders

于 2019-07-17T18:17:55.347 回答