Cordova iPhone X безопасная зона после изменения макета / ориентации. - PullRequest
0 голосов
/ 14 ноября 2018

Я использую переменную CSS safe-area-inset-top в своем приложении Cordova для обработки безопасной области iPhone X:

body {
 padding-top: env(safe-area-inset-top);
}

Работает, как и ожидалось, при загрузке приложения.Однако, когда я вхожу и выхожу из полноэкранного (принудительного пейзажа) AVPlayer через пользовательский плагин и возвращаюсь в портретное приложение, отступы исчезают, и мое приложение частично отключается.

В настоящее время я используюэто в моем классе AVPlayerViewController в плагине для iOS.

LandscapeVideo.m

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight; // or LandscapeLeft
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

Заранее благодарен за любую помощь / идеи!

Ответы [ 3 ]

0 голосов
/ 10 января 2019

Исправлена ​​проблема с поворотом экрана iPhone X / XS

В iPhone X / XS поворот экрана заставит высоту панели заголовка использовать неверное значение, поскольку расчет безопасного-area-inset- * не отражает новые значения во время обновления пользовательского интерфейса.Эта ошибка существует в UIWebView даже в последней версии iOS 12. Обходной путь - вставить верхнее поле в 1 пиксель, а затем быстро обратить его, что приведет к немедленному пересчету safe-area-inset- *.Исправление несколько уродливое, но оно работает, если вам по той или иной причине придется остаться с UIWebView.

window.addEventListener("orientationchange", function() {
    var originalMarginTop = document.body.style.marginTop;
    document.body.style.marginTop = "1px";
    setTimeout(function () {
        document.body.style.marginTop = originalMarginTop;
    }, 100);
}, false);

Цель кода - заставить документ.body.style.marginTop слегка измениться, а затем повернуть его вспять.Это не обязательно должно быть "1px".Вы можете выбрать значение, которое не вызывает мерцание вашего пользовательского интерфейса, но достигает своей цели.

0 голосов
/ 17 мая 2019

Спасибо @pascalzon и @YYL за полезную информацию. Я попытался переключиться на WKWebView для своего приложения Cordova, но оно просто сломало его, поэтому на данный момент я застрял с uiWebview и, таким образом, с этой проблемой.

Я хочу, чтобы мое приложение выглядело хорошо на устройствах с надрезом, таких как iPhone X, поэтому я добавил viewport-fit=cover в объявление области просмотра приложения и начал играть с безопасными вставками. Мои макеты достаточно просты. Верхнее поле должно быть 1rem или safe-area-inset-top, если значение больше 1rem.

К сожалению, функция CSS max () пока не является стандартной. Если бы я мог использовать это, все было бы проще (при условии, что все преобразуется в пиксели).

:root {
    --app-margin-top-default: 1rem;
    --app-margin-top: max(env(safe-area-inset-top), var(--app-margin-top-default));
}

Так что я был вынужден выполнить максимальное сравнение в javascript, а затем установить --app-margin-top оттуда каждый раз, когда изменялась ориентация экрана.

Поскольку, похоже, пока что нет способа чтения переменных env CSS из javascript, я начинаю с CSS, записывая вставки безопасной области в переменные CSS, к которым я могу получить доступ позже из javascript. Значения по умолчанию:

:root {
    --safe-area-inset-top:      0px;
    --safe-area-inset-right:    0px;
    --safe-area-inset-bottom:   0px;
    --safe-area-inset-left:     0px;
}

Затем я установил эти переменные следующим образом:

/* iOS 11.0: supports constant() css function. (Assume all other inset vars are supported.) */
@supports (padding-top: constant(safe-area-inset-top))  {
    :root {
        --safe-area-inset-top:      constant(safe-area-inset-top, 0);
        --safe-area-inset-right:    constant(safe-area-inset-right, 0);
        --safe-area-inset-bottom:   constant(safe-area-inset-bottom, 0);
        --safe-area-inset-left:     constant(safe-area-inset-left, 0);
    }
}
/* iOS 11.2 and latest Chrome webviews support the env() css function. (Assume all other inset vars are supported.) */
@supports (padding-top: env(safe-area-inset-top))  {
    :root {
        --safe-area-inset-top:      env(safe-area-inset-top, 0);
        --safe-area-inset-right:    env(safe-area-inset-right, 0);
        --safe-area-inset-bottom:   env(safe-area-inset-bottom, 0);
        --safe-area-inset-left:     env(safe-area-inset-left, 0);
    }
}

Каждый раз, когда изменялась ориентация экрана, я сравнивал --safe-area-inset-top с --app-margin-top-default и устанавливал для --app-margin-top максимальное из этих значений. Именно тогда я столкнулся с этой проблемой. Казалось, что между изменением ориентации экрана и моими переменными вставки безопасной области CSS произошла задержка. Таким образом, мой код установки полей не работал.

Я попробовал уловку YYL, чтобы заставить пересчитать вставки безопасной зоны, но, похоже, это не сработало. В конце концов вставки были обновлены, но после того, как мой слушатель события изменения ориентации экрана завершил выполнение :(

Мое решение

В этом решении используется плагин ориентации экрана Cordova:

https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-screen-orientation/

Единственный раз, когда вы можете полагаться на правильность значений вставки безопасной области, это при запуске приложения, поэтому я записываю их в набор переменных javascript внутри моего app объекта:

safeAreaInsetNorth: undefined,
safeAreaInsetEast: undefined,
safeAreaInsetSouth: undefined,
safeAreaInsetWest: undefined,

Метод, который устанавливает эти переменные при запуске, учитывает ориентацию экрана.

console.log("Screen orientation at startup is: " +screen.orientation.type);
let $root = $(":root");
// Notch/North at the top.
if (screen.orientation.type.match("portrait-primary")) {
    app.safeAreaInsetNorth = $root.css("--safe-area-inset-top");
    app.safeAreaInsetEast  = $root.css("--safe-area-inset-right");
    app.safeAreaInsetSouth = $root.css("--safe-area-inset-bottom");
    app.safeAreaInsetWest  = $root.css("--safe-area-inset-left");
}
// Upside down... Notch/North at the bottom.
else if (screen.orientation.type.match("portrait-secondary")) {
    app.safeAreaInsetNorth = $root.css("--safe-area-inset-bottom");
    app.safeAreaInsetEast  = $root.css("--safe-area-inset-left");
    app.safeAreaInsetSouth = $root.css("--safe-area-inset-top");
    app.safeAreaInsetWest  = $root.css("--safe-area-inset-right");
}
// Notch/North to the left.
else if (screen.orientation.type.match("landscape-primary")) {
    app.safeAreaInsetNorth = $root.css("--safe-area-inset-left");
    app.safeAreaInsetEast  = $root.css("--safe-area-inset-top");
    app.safeAreaInsetSouth = $root.css("--safe-area-inset-right");
    app.safeAreaInsetWest  = $root.css("--safe-area-inset-bottom");
}
// Notch/North to the right.
else if (screen.orientation.type.match("landscape-secondary")) {
    app.safeAreaInsetNorth = $root.css("--safe-area-inset-right");
    app.safeAreaInsetEast  = $root.css("--safe-area-inset-bottom");
    app.safeAreaInsetSouth = $root.css("--safe-area-inset-left");
    app.safeAreaInsetWest  = $root.css("--safe-area-inset-top");
} else {
    throw "I have no idea which way up I am!";
}

При запуске, а затем снова каждый раз, когда меняется ориентация экрана, я проверяю, нужно ли мне обновлять --app-margin-top следующим образом:

let marginTopDefault = app.getGlobalCssVariableInPx("--app-margin-top-default");
let newMarginTop = undefined;
switch(screen.orientation.type) {
    case "portrait-primary": // Notch/North at the top.
        newMarginTop = app.safeAreaInsetNorth;
        break;
    case "portrait-secondary": // Upside down... Notch/North at the bottom.
        newMarginTop = app.safeAreaInsetSouth;
        break;
    case "landscape-primary": // Notch/North to the left.
        newMarginTop = app.safeAreaInsetEast;
        break;
    case "landscape-secondary": // Notch/North to the right.
        newMarginTop = app.safeAreaInsetWest;
        break;
    default:
        throw "No idea which way up I am!";
}

app.getGlobalCssVariableInPx - вспомогательная функция, которая конвертирует rems в пиксели, умножая их на базовый размер шрифта.

Затем я конвертирую marginTopDefault и newMarginTop в целые числа, нахожу максимальное значение и задаю --app-margin-top для этого.

    $(":root").css("--app-margin-top", Math.max(marginTopDefault, newMarginTop) + "px");

Заключение

Я думаю, что описал это достаточно хорошо. Было очень сложно найти что-то работающее, что должно было сработать, но эй. Вот так иногда. И я не гуру HTML5, так что, возможно, есть способы, которыми это можно упростить.

0 голосов
/ 28 ноября 2018

Как видно из примечаний об ориентации устройства в этом ответе: https://stackoverflow.com/a/46232813/1085272

Существует проблема safe-area-inset-xxx после некоторых изменений ориентации при использовании uiWebView (который используется по умолчанию).

Переход на WKWebView (например, с помощью cordova-plugin-wkwebview-engine) исправил проблему для меня.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...