← 모든 확장

네이티브 확장

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 커버 화면에서는 인터페이스가 일반 휴대폰용으로 배치된 뒤 맞게 축소됩니다.

Pixel 9 Pro Fold 및 Galaxy Z Flip 기기 프로필의 Android 에뮬레이터에서 테스트되었습니다.

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에서 오늘 이를 처리합니다.

HARMAN AIR 51.4.1로 Xcode 27 시뮬레이터(iPhone Duo)에서 테스트되었습니다.

기능

  • 독립형: 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()단일 인스턴스를 반환합니다.
isSupportedAndroid와 iOS에서는 true입니다. 그 외에는 false이며, 이 경우 모든 호출은 아무 동작도 하지 않습니다.
setSensorLandscape()기기와 함께 회전하는 양쪽 가로 모드입니다. stage.setAspectRatio(StageAspectRatio.LANDSCAPE) 뒤에 호출하세요. Android용이며, iOS에서는 LANDSCAPE가 이미 양쪽을 허용합니다.
displayRotation현재 디스플레이 회전을 도(0, 90, 180, 270)로 반환하며, 알 수 없으면 -1입니다.
watchFold( stage )가로 모드 고정이 없어도 접힘 및 커버 화면 변경을 감시하기 시작합니다. iOS에서 iPhone Duo를 쓰려면 스테이지가 필요합니다.
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 코드.

이벤트

deviceTypeChangedphone · tablet · cover (cover: Galaxy Z Flip 외부 화면, Android). watchFold(stage) 뒤에 전송되며, Android에서는 setSensorLandscape() 뒤에도 전송됩니다. 변경 시에만 전송됩니다.

KlugLayout 구매

AIR 애플리케이션 1개에 대한 연간 라이선스이며 12개월간 모든 업데이트를 제공합니다. 결제 후 확장, ActionScript 라이브러리, 문서를 이메일로 보내 드리며, 보통 영업일 기준 1일 이내입니다. 라이선스 및 약관

심플
€19 / 년
  • AIR 애플리케이션 1개에 대한 라이선스
  • 12개월간 모든 업데이트
  • 지원 없음
심플 구매
스탠더드
€149 / 년
  • AIR 애플리케이션 1개에 대한 라이선스
  • 12개월간 모든 업데이트
  • 7일 이내 이메일 답변
스탠더드 구매
프라이어리티
€299 / 년
  • AIR 애플리케이션 1개에 대한 라이선스
  • 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에서 테스트됨
권한없음