← Все расширения

Нативное расширение

KlugLayout

com.klug.layout

APM НЕ НУЖЕН. Скачайте и пользуйтесь. Проще уже некуда.

Раскладка экрана для планшетов и складных устройств Android и для iPhone Duo: альбомная ориентация с обеих сторон, а приложение знает, когда Fold, Flip или iPhone Duo открывается или закрывается.

Android iOS В продакшене От €19 / год · Купить

Обзор

Некоторые приложения рассчитаны только на альбомную ориентацию, например станция с камерой на планшете. Но пользователи всё равно ожидают, что изображение будет ориентировано правильно, как бы они ни положили устройство: с кнопками слева или справа.

KlugLayout устанавливает ориентацию экрана Android в альбомную с обеих сторон. Приложение остаётся в альбомной ориентации, но поворачивается на 180 градусов вместе с устройством. Он также сообщает текущий поворот дисплея, чтобы приложение могло подстраивать собственное содержимое, например изображение с камеры, под то, как держат устройство.

Складные устройства меняют экран во время работы приложения. Galaxy Z Fold или Pixel Fold в раскрытом виде — планшет, в сложенном — телефон; Galaxy Z Flip переходит с высокого основного дисплея на маленький почти квадратный внешний экран. Когда устройство переносит приложение на другой дисплей, сцена AIR не всегда получает событие изменения размера, а стартовые значения размера экрана и выреза камеры остаются значениями первого дисплея. KlugLayout отслеживает это на нативном уровне и сообщает приложению, на каком типе экрана оно сейчас находится.

KlugLayout ежедневно используется в наших приложениях на планшетах Android, нашем доказательстве работоспособности.

Складные устройства

KlugLayout относит текущее окно к одному из трёх классов и отправляет событие при каждой смене класса:

tabletБольшой дисплей. Пример: раскрытый Galaxy Z Fold или Pixel Fold.
phoneДисплей размером с телефон. Пример: сложенный Fold или основной дисплей Flip.
coverМаленький внешний дисплей. Пример: внешний экран Galaxy Z Flip.

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

В наших приложениях принимающая сторона выходит из аккаунта и входит снова при каждой смене режима Fold или внешнего экрана, чтобы прямые трансляции всегда чисто запускались на новом экране. На внешнем экране Flip интерфейс строится как для обычного телефона и уменьшается по размеру.

Протестировано в эмуляторе Android на профилях устройств Pixel 9 Pro Fold и Galaxy Z Flip.

iPhone Duo

iPhone Duo — первый складной iPhone от Apple: телефон в сложенном виде, небольшой планшет в раскрытом. AIR сам за ним не следует. Когда устройство раскрывают, iOS может оставить приложение в телефонном окне с чёрными полями, событие изменения размера не приходит, а стартовые значения экрана остаются значениями внешнего дисплея.

KlugLayout определяет на iOS, на каком дисплее находится приложение, и отправляет то же событие DEVICE_TYPE_CHANGED, что и на Android: "phone", когда Duo сложен, "tablet", когда раскрыт. Один и тот же код работает на обеих платформах.

Статус: основные раскладки решены. Работают раскладки в сложенном и раскрытом виде, складывание и раскрытие во время работы приложения, поворот раскрытого устройства и центрированные нативные диалоги. Настройки трансляции и камеры ещё предстоит протестировать на реальном устройстве.

Ждать AIR 52 нет причин: с апреля 2027 года загрузки в App Store должны собираться с SDK iOS 27, и с этого момента приложение AIR встречает iPhone Duo как складное устройство. KlugLayout справляется с этим уже сегодня, с AIR 51.4.1.

Протестировано в симуляторе Xcode 27 (iPhone Duo) с HARMAN AIR 51.4.1.

Возможности

  • Автономность: один ANE, без базовой библиотеки и зависимых ANE
  • Альбомная ориентация с обеих сторон, поворот вместе с устройством
  • Определение складывания: планшет, телефон или внешний экран Flip, с событием при каждом изменении
  • iPhone Duo: телефон в сложенном виде, планшет в раскрытом, с тем же событием, что и на Android
  • Блокировка альбомной ориентации автоматически снимается, пока Fold сложен
  • Размер и вырез камеры текущего дисплея, в том числе после складывания
  • Без перехода в портретную ориентацию
  • Текущий поворот дисплея: 0, 90, 180 или 270 градусов
  • Активно с самого запуска приложения
  • На других платформах ничего не делает, поэтому код можно оставить в кроссплатформенном приложении

Поддерживаемые платформы

Android arm64 · armv7
iOS arm64 · iPhone Duo

Начало работы

Добавьте расширение в дескриптор вашего приложения:

app.xml
<extensions>
    <extensionID>com.klug.layout</extensionID>
</extensions>

Приложениям с целевой платформой Android 16 следует также разрешить фиксированную ориентацию на больших экранах с помощью этого свойства внутри <application> в дополнениях манифеста:

app.xml
<property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY"
          android:value="true"/>

Примеры кода

Четыре полных сценария из API, который работает в наших приложениях. Вызовы возвращаются сразу; изменения экрана приходят в виде StatusEvent. Полная документация →

1 · Альбомная ориентация с обеих сторон
Main.as
import com.klug.layout.KlugLayout;
import flash.display.StageAspectRatio;
import flash.events.StageOrientationEvent;

var layout:KlugLayout = KlugLayout.getInstance();

// isSupported is false on desktop platforms: every call below is then a no-op,
// so this code can stay in a cross-platform app
stage.autoOrients = true;
stage.setAspectRatio( StageAspectRatio.LANDSCAPE );   // first AIR's landscape ...
layout.setSensorLandscape();                          // ... then both sides on Android
                                                      // (on iOS LANDSCAPE already allows both sides)

// turn your own content, such as a camera picture, with the device
updatePicture();
stage.addEventListener( StageOrientationEvent.ORIENTATION_CHANGE, function( e:StageOrientationEvent ):void {
    updatePicture();
});

function updatePicture():void
{
    var rotation:int = layout.displayRotation;   // 0, 90, 180 or 270; -1 = unknown
    if ( rotation != -1 ) rotateCameraPicture( rotation );   // your app function
}
2 · Реакция на раскрытие или складывание устройства
Fold.as
import flash.events.StatusEvent;

layout.addEventListener( StatusEvent.STATUS, onLayout );
layout.watchFold( stage );   // pass the stage: iOS needs it for the iPhone Duo

// events report changes only; read the class once for the start
var startClass:String = layout.deviceClass;   // "phone", "tablet", "cover" or "" (unknown)
showLayoutFor( startClass != "" ? startClass : chooseFromStage() );   // your own default

function onLayout( e:StatusEvent ):void
{
    if ( e.code != KlugLayout.DEVICE_TYPE_CHANGED ) return;
    showLayoutFor( e.level );   // "tablet" or "phone"; "cover" on a Galaxy Z Flip (Android)
}

// fold-only behaviour, kept away from normal phones and tablets
if ( layout.isFoldable ) enableFoldHints();   // your app function
3 · Раскладка под дисплей, на котором сейчас приложение
Layout.as
function showLayoutFor( deviceClass:String ):void
{
    // size of the current window in pixels, also after the device moved the app
    // to its other display; -1 = unknown, then fall back to the stage
    var w:int = layout.windowWidth  > 0 ? layout.windowWidth  : stage.stageWidth;
    var h:int = layout.windowHeight > 0 ? layout.windowHeight : stage.stageHeight;

    // top inset of the current display (Android: camera cutout, from Android 9)
    var top:int = Math.max( 0, layout.safeInsetTop );   // -1 = unknown

    if ( deviceClass == "tablet" )
        buildTabletViews( w, h, top );            // your app functions
    else
    {
        buildPhoneViews( w, h, top );
        if ( deviceClass == "cover" ) scaleToFit( w, h );   // phone layout, scaled down
    }
}
4 · Выход из блокировки альбомной ориентации и повторный вход
Screens.as
// while a Fold is closed the lock is suspended on its own and comes back when it is opened.
// release() is for screens where the app itself leaves landscape (Android; no-op on iOS).
function openPortraitScreen():void
{
    layout.release();                                   // remove the landscape lock
    stage.setAspectRatio( StageAspectRatio.PORTRAIT );  // AIR decides again
}

function openStationScreen():void
{
    stage.setAspectRatio( StageAspectRatio.LANDSCAPE );
    layout.setSensorLandscape();                        // both landscape sides again
}

Обзор API

KlugLayout.getInstance()Возвращает единственный экземпляр.
isSupportedTrue на Android и iOS. False на остальных; тогда каждый вызов ничего не делает.
setSensorLandscape()Альбомная ориентация с обеих сторон, поворот вместе с устройством. Вызывайте после stage.setAspectRatio(StageAspectRatio.LANDSCAPE). Android; на iOS LANDSCAPE уже допускает обе стороны.
displayRotationТекущий поворот дисплея в градусах (0, 90, 180, 270) или -1.
watchFold( stage )Начинает отслеживать изменения складывания и внешнего экрана, в том числе без блокировки альбомной ориентации. На iOS для iPhone Duo нужна сцена (stage).
isFoldableTrue на складном оборудовании: складные устройства Android (Android 11 или новее) и iPhone Duo.
release()Снимает блокировку альбомной ориентации, например когда приложение переключается на телефонную раскладку. Android; на iOS ничего не делает.
deviceClassТекущий класс: "phone", "tablet" или "cover"; "" пока неизвестен. На iOS доступен после watchFold(stage) на iPhone Duo.
windowWidth / windowHeightРазмер текущего окна в пикселях, следует за устройством на другой дисплей; -1, если неизвестен.
safeInsetTopВерхний отступ текущего дисплея в пикселях: вырез камеры на Android (Android 9 или новее), верхняя безопасная область на iOS; -1, если неизвестен.
DEVICE_TYPE_CHANGEDКод StatusEvent, отправляемый при каждой смене класса.

События

deviceTypeChangedphone · tablet · cover (cover: внешний экран Galaxy Z Flip, Android). Отправляется после watchFold(stage), на Android также после setSensorLandscape(); только при изменениях.

Купить KlugLayout

Годовая лицензия на одно приложение AIR со всеми обновлениями в течение 12 месяцев. После оплаты вы получаете расширение, библиотеку ActionScript и документацию по e-mail, обычно в течение одного рабочего дня. Лицензия и условия

Базовый
€19 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Без поддержки
Купить Базовый
Стандартный
€149 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 7 дней
Купить Стандартный
Приоритетный
€299 / год
  • Лицензия на одно приложение AIR
  • Все обновления в течение 12 месяцев
  • Ответ по e-mail в течение 48 часов
Купить Приоритетный
Налоги рассчитываются при оформлении заказа через Link (Stripe). ID приложения вашего приложения AIR вы указываете при оформлении заказа.

Требования

AIR SDK51.x (HARMAN)
AndroidAndroid 6.0 (API 23) или новее; вырез камеры — с Android 9 (API 28)
iOSiOS 13 или новее; iPhone Duo протестирован с AIR 51.4.1
РазрешенияНет