← All extensions

Native extension

KlugLayout

com.klug.layout

NO APM NEEDED. Download and enjoy. It can’t get any simpler. Just update the Adobe AIR SDK. If you need help, we are here.

Screen layout for Android tablets and foldables and for the iPhone Duo: landscape on both sides, and the app knows when a Fold, Flip or iPhone Duo is opened or closed.

Android iOS In production From €9 / year · Buy

Overview

Some apps are designed for landscape only, for example a camera station on a tablet. Users still expect the picture to be the right way up however they place the device: with the buttons on the left or on the right.

KlugLayout sets the Android screen orientation to landscape on both sides. The app stays in landscape, but turns by 180 degrees with the device. It also reports the current display rotation, so an app can adapt its own content, such as a camera picture, to how the device is held.

Foldables change the screen while the app is running. A Galaxy Z Fold or Pixel Fold is a tablet when opened and a phone when closed; a Galaxy Z Flip moves from its tall main display to a small, almost square cover screen. When the device moves the app to the other display, the AIR stage does not always receive a resize event, and the start-up values for screen size and camera cutout stay those of the first display. KlugLayout watches this natively and tells the app what kind of screen it is on now.

KlugLayout is in daily use in our apps on Android tablets, our proof of concept.

Foldables

KlugLayout sorts the current window into one of three classes and sends an event whenever the class changes:

tabletThe large display. Example: an opened Galaxy Z Fold or Pixel Fold.
phoneA phone-sized display. Example: a closed Fold, or the main display of a Flip.
coverA small outer display. Example: the cover screen of a Galaxy Z Flip.

When a Fold is closed, the landscape lock is suspended so the phone-sized outer screen can use portrait, and it comes back when the device is opened again. The app also gets the size and the camera cutout of the current display, so a layout built after folding fits the screen it is shown on.

In our apps the viewing side signs out and signs in again on every fold or cover change, so live streams always start cleanly on the new screen. On the Flip cover the interface is laid out for a normal phone and scaled down to fit.

Tested in the Android emulator on Pixel 9 Pro Fold and Galaxy Z Flip device profiles.

iPhone Duo

The iPhone Duo is Apple's first foldable: a phone when closed, a small tablet when opened. AIR does not follow it on its own. When the device is opened, iOS can keep the app in its letterboxed phone window, no resize event arrives, and the start-up screen values stay those of the outer display.

KlugLayout detects on iOS which display the app is on and sends the same DEVICE_TYPE_CHANGED event as on Android: "phone" when the Duo is closed, "tablet" when it is opened. The same code serves both platforms.

Status: the basic layouts are solved. Closed and opened layouts, folding and unfolding while the app is running, rotating the opened device and centred native dialogs work. Streaming and camera settings still have to be tested on the real device.

There is no reason to wait for AIR 52: from April 2027 App Store uploads have to be built with the iOS 27 SDK, and from then on an AIR app meets the iPhone Duo as the foldable it is. KlugLayout handles it today, with AIR 51.4.1.

Tested in the Xcode 27 simulator (iPhone Duo) with HARMAN AIR 51.4.1.

Features

  • Self-contained: one ANE, no core library or dependency ANEs to add
  • Landscape on both sides, turning with the device
  • Fold detection: tablet, phone or Flip cover screen, with an event on every change
  • iPhone Duo: phone when closed, tablet when opened, with the same event as on Android
  • Landscape lock released automatically while a Fold is closed
  • Size and camera cutout of the current display, also after folding
  • No switch to portrait
  • Current display rotation: 0, 90, 180 or 270 degrees
  • Active from the start of the app
  • Does nothing on other platforms, so the code can stay in a cross-platform app

Supported platforms

Android arm64 · armv7
iOS arm64 · iPhone Duo

Getting started

Add the extension to your application descriptor:

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

Apps targeting Android 16 should also allow a fixed orientation on large screens with this property inside <application> of the manifest additions:

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

Code examples

Four complete flows, taken from the API that runs in our apps. Calls return at once; changes of the screen arrive as a StatusEvent. Full documentation →

1 · Landscape on both sides
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 · React when a foldable is opened or closed
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 · Lay out for the display the app is on now
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 · Leave and re-enter the landscape lock
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 overview

KlugLayout.getInstance()Returns the single instance.
isSupportedTrue on Android and iOS. False elsewhere; every call is then a no-op.
setSensorLandscape()Landscape on both sides, turning with the device. Call it after stage.setAspectRatio(StageAspectRatio.LANDSCAPE). Android; on iOS LANDSCAPE already allows both sides.
displayRotationThe current display rotation in degrees (0, 90, 180, 270), or -1.
watchFold( stage )Starts watching for fold and cover-screen changes, also without a landscape lock. On iOS the stage is needed for the iPhone Duo.
isFoldableTrue on foldable hardware: Android foldables (Android 11 or later) and the iPhone Duo.
release()Removes the landscape lock, for example when the app switches to a phone layout. Android; no-op on iOS.
deviceClassThe current class: "phone", "tablet" or "cover"; "" while unknown. On iOS available after watchFold(stage) on the iPhone Duo.
windowWidth / windowHeightSize of the current window in pixels, following the device to its other display; -1 when unknown.
safeInsetTopTop inset of the current display in pixels: the camera cutout on Android (Android 9 or later), the top safe area on iOS; -1 when unknown.
DEVICE_TYPE_CHANGEDStatusEvent code sent on every change of the class.

Events

deviceTypeChangedphone · tablet · cover (cover: Galaxy Z Flip outer screen, Android). Sent after watchFold(stage), on Android also after setSensorLandscape(); on changes only.

Buy KlugLayout

A yearly licence for one AIR application, with all updates for 12 months. After payment you receive the extension, the ActionScript library and the documentation by e-mail, usually within one business day. Licence and terms

Simple
€9 / year
  • Licence for one AIR application
  • All updates for 12 months
  • No support
Buy Simple
Standard
€39 / year
  • Licence for one AIR application
  • All updates for 12 months
  • Answer by e-mail within 7 days
Buy Standard
Priority
€79 / year
  • Licence for one AIR application
  • All updates for 12 months
  • Answer by e-mail within 48 hours
Buy Priority
Taxes are calculated at checkout by Link (Stripe). You enter the application ID of your AIR app during checkout.

Requirements

AIR SDK51.x (HARMAN)
AndroidAndroid 6.0 (API 23) or later; camera cutout from Android 9 (API 28)
iOSiOS 13 or later; iPhone Duo tested with AIR 51.4.1
PermissionsNone