NULL оконные вставки
Я пытаюсь получить 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());
}
1 ответ
getRootWindowInsets возвращает ноль тогда и только тогда, когда представление отключено. Убедитесь, что вы звоните из правильного контекста.
Вы должны поставить свой код на
@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());
}
}
Мне пришлось использовать комбинацию 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;
}
}
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(это, getWindow(). GetDecorView());
Это происходило для меня при запуске эмулятора. Похоже, даже если у вас есть эмулятор со скином по умолчанию, который имеет вырез экрана, он все равно может не зарегистрировать его в качестве устройства отключения дисплея.
Вы можете обойти это, включив опцию "Имитация дисплея с вырезом" в опциях разработчика:
https://developer.android.com/guide/topics/display-cutout/
Попробуйте ниже код. Мне удалось получить высоту строки состояния с помощью 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()