← 所有扩展

原生扩展

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 合上时,横屏锁定会暂停,以便手机尺寸的外屏使用竖屏,设备再次展开后锁定恢复。应用还会获得当前屏幕的大小和摄像头挖孔信息,因此折叠后构建的布局可适配其所显示的屏幕。

在我们的应用中,观看端会在每次折叠或外屏变化时退出并重新登录,因此实时流总能在新屏幕上干净地启动。在 Flip 外屏上,界面按普通手机布局并缩小以适配。

已在 Android 模拟器中使用 Pixel 9 Pro Fold 和 Galaxy Z Flip 设备配置文件测试。

iPhone Duo

iPhone Duo 是 Apple 的首款折叠屏设备:合上时是手机,展开时是小型平板。AIR 自己无法跟随这种变化。设备展开时,iOS 可能让应用保持在带黑边的手机窗口中,不会收到尺寸变化事件,启动时的屏幕数值仍是外屏的数值。

KlugLayout 在 iOS 上检测应用所处的屏幕,并发送与 Android 上相同的 DEVICE_TYPE_CHANGED 事件:Duo 合上时为 "phone",展开时为 "tablet"。同一份代码适用于两个平台。

状态:基本布局已解决。合上和展开的布局、应用运行期间的折叠与展开、旋转展开状态的设备以及居中的原生对话框均可正常工作。推流和摄像头设置仍需在真机上测试。

没有理由等待 AIR 52:从 2027 年 4 月起,上传到 App Store 的应用必须使用 iOS 27 SDK 构建,此后 AIR 应用将把 iPhone Duo 视为它本来的样子,即折叠屏设备。KlugLayout 现在就能处理,使用 AIR 51.4.1 即可。

已在 Xcode 27 模拟器 (iPhone Duo) 中使用 HARMAN AIR 51.4.1 测试。

特性

  • 自成一体:一个 ANE,无需添加核心库或依赖 ANE
  • 两侧横屏,随设备旋转
  • 折叠检测:tablet、phone 或 Flip 外屏,每次变化都会触发事件
  • iPhone Duo:合上时为 phone,展开时为 tablet,事件与 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()返回唯一实例。
isSupported在 Android 和 iOS 上为 True。在其他平台为 False;此时每次调用都不执行任何操作。
setSensorLandscape()两侧横屏,随设备旋转。请在 stage.setAspectRatio(StageAspectRatio.LANDSCAPE) 之后调用。适用于 Android;在 iOS 上,LANDSCAPE 本身已允许两侧横屏。
displayRotation当前显示旋转角度(单位为度:0、90、180、270),或 -1。
watchFold( stage )开始监视折叠和外屏变化,无需横屏锁定也可使用。在 iOS 上,iPhone Duo 需要传入 stage。
isFoldable在折叠屏硬件上为 True:Android 折叠屏设备(Android 11 或更高版本)和 iPhone Duo。
release()解除横屏锁定,例如当应用切换到手机布局时。适用于 Android;在 iOS 上不执行任何操作。
deviceClass当前类别:"phone"、"tablet" 或 "cover";未知时为 ""。在 iOS 上,仅在 iPhone Duo 上调用 watchFold(stage) 之后可用。
windowWidth / windowHeight当前窗口的大小(像素),会随设备切换到另一块屏幕;未知时为 -1。
safeInsetTop当前屏幕的顶部边距(像素):Android 上为摄像头挖孔(Android 9 或更高版本),iOS 上为顶部安全区域;未知时为 -1。
DEVICE_TYPE_CHANGED每次类别变化时发送的 StatusEvent code。

事件

deviceTypeChangedphone · tablet · cover(cover:Galaxy Z Flip 外屏,Android)。在 watchFold(stage) 之后发送,在 Android 上也会在 setSensorLandscape() 之后发送;仅在发生变化时发送。

购买 KlugLayout

一个 AIR 应用的年度许可,含 12 个月内的所有更新。付款后,您将通过电子邮件收到扩展、ActionScript 库和文档,通常在一个工作日内。许可与条款

基础版
€19 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 不含支持
购买基础版
标准版
€149 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 7 天内通过电子邮件答复
购买标准版
优先版
€299 / 年
  • 一个 AIR 应用的许可
  • 12 个月内的所有更新
  • 48 小时内通过电子邮件答复
购买优先版
税费在结账时由 Link (Stripe) 计算。您需要在结账时输入 AIR 应用的应用 ID。

要求

AIR SDK51.x (HARMAN)
AndroidAndroid 6.0 (API 23) 或更高版本;摄像头挖孔需 Android 9 (API 28) 起
iOSiOS 13 或更高版本;iPhone Duo 已使用 AIR 51.4.1 测试
权限无