簡體   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