繁体   English   中英

NULL 窗口插入

[英]NULL Window Insets

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

你应该把你的代码放在

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

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

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

试试下面的代码。 我能够使用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;
    }

您可以在处理程序中获得 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()

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

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

我不得不使用OnApplyWindowInsetsListener的组合并从DecorView获取DisplayCutout

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;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM