空窗口插入

时间:2018-12-01 21:08:49

标签: android windowinsets display-cutouts

我正在尝试获取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());
}

7 个答案:

答案 0 :(得分:1)

getRootWindowInsets仅在视图分离时才返回null。确保从正确的上下文中调用它。

答案 1 :(得分: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());

答案 2 :(得分: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;
    }

答案 3 :(得分: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()

答案 4 :(得分:0)

您应该将代码放在

@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());
    }
}

答案 5 :(得分:0)

这是我在运行模拟器时发生的。看起来,即使您的模拟器具有带有显示切口的默认外观,它仍然可能不会将其注册为显示切口设备。

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

答案 6 :(得分:0)

我必须使用OnApplyWindowInsetsListener的组合,并从DisplayCutout获得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;
    }
}