Visão geral
Alguns apps são projetados apenas para paisagem, por exemplo uma estação de câmera em um tablet. Ainda assim, os usuários esperam que a imagem fique na posição certa, qualquer que seja o modo de apoiar o dispositivo: com os botões à esquerda ou à direita.
O KlugLayout define a orientação de tela do Android como paisagem nos dois lados. O app permanece em paisagem, mas gira 180 graus junto com o dispositivo. Ele também informa a rotação atual da tela, para que um app possa adaptar o próprio conteúdo, como a imagem da câmera, à forma como o dispositivo é segurado.
Os dobráveis mudam a tela enquanto o app está em execução. Um Galaxy Z Fold ou Pixel Fold é um tablet quando aberto e um celular quando fechado; um Galaxy Z Flip passa da tela principal alta para uma pequena tela externa, quase quadrada. Quando o dispositivo move o app para a outra tela, o palco do AIR nem sempre recebe um evento de redimensionamento, e os valores iniciais de tamanho de tela e de recorte da câmera continuam sendo os da primeira tela. O KlugLayout monitora isso nativamente e informa ao app em que tipo de tela ele está agora.
O KlugLayout é usado diariamente em nossos apps em tablets Android, nossa prova de conceito.
Dobráveis
O KlugLayout classifica a janela atual em uma de três classes e envia um evento sempre que a classe muda:
| tablet | A tela grande. Exemplo: um Galaxy Z Fold ou Pixel Fold aberto. |
| phone | Uma tela do tamanho de um celular. Exemplo: um Fold fechado, ou a tela principal de um Flip. |
| cover | Uma pequena tela externa. Exemplo: a tela externa de um Galaxy Z Flip. |
Quando um Fold é fechado, o bloqueio de paisagem é suspenso para que a tela externa, do tamanho de um celular, possa usar retrato, e ele volta quando o dispositivo é aberto de novo. O app também recebe o tamanho e o recorte da câmera da tela atual, de modo que um layout montado após a dobra se ajuste à tela em que é exibido.
Em nossos apps, o lado de visualização faz logout e login novamente a cada mudança de dobra ou de tela externa, para que os streams ao vivo sempre iniciem limpos na nova tela. Na tela externa do Flip, a interface é montada como para um celular normal e reduzida para caber.
Testado no emulador Android com os perfis de dispositivo Pixel 9 Pro Fold e Galaxy Z Flip.
iPhone Duo
O iPhone Duo é o primeiro dobrável da Apple: um celular quando fechado, um pequeno tablet quando aberto. O AIR não o acompanha por conta própria. Quando o dispositivo é aberto, o iOS pode manter o app em sua janela de celular com letterbox, nenhum evento de redimensionamento chega e os valores iniciais da tela continuam sendo os da tela externa.
O KlugLayout detecta no iOS em qual tela o app está e envia o mesmo evento DEVICE_TYPE_CHANGED do Android: "phone" quando o Duo está fechado, "tablet" quando está aberto. O mesmo código atende as duas plataformas.
Status: os layouts básicos estão resolvidos. Layouts fechado e aberto, dobrar e abrir com o app em execução, girar o dispositivo aberto e diálogos nativos centralizados funcionam. Os ajustes de streaming e câmera ainda precisam ser testados no dispositivo real.
Não há motivo para esperar pelo AIR 52: a partir de abril de 2027, os envios à App Store precisam ser compilados com o SDK do iOS 27, e a partir daí um app AIR encontra o iPhone Duo como o dobrável que ele é. O KlugLayout cuida disso hoje, com o AIR 51.4.1.
Testado no simulador do Xcode 27 (iPhone Duo) com o HARMAN AIR 51.4.1.
Recursos
- Autossuficiente: uma ANE, sem biblioteca principal nem ANEs de dependência para adicionar
- Paisagem nos dois lados, girando junto com o dispositivo
- Detecção de dobra: tablet, celular ou tela externa do Flip, com um evento a cada mudança
- iPhone Duo: celular quando fechado, tablet quando aberto, com o mesmo evento do Android
- Bloqueio de paisagem liberado automaticamente enquanto um Fold está fechado
- Tamanho e recorte da câmera da tela atual, também após a dobra
- Sem troca para retrato
- Rotação atual da tela: 0, 90, 180 ou 270 graus
- Ativo desde o início do app
- Não faz nada em outras plataformas, então o código pode permanecer em um app multiplataforma
Plataformas compatíveis
Primeiros passos
Adicione a extensão ao descritor do seu aplicativo:
<extensions>
<extensionID>com.klug.layout</extensionID>
</extensions>
Apps voltados ao Android 16 também devem permitir uma orientação fixa em telas grandes com esta propriedade, dentro de <application> das adições ao manifesto:
<property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true"/>
Exemplos de código
Quatro fluxos completos, extraídos da API que roda em nossos apps. As chamadas retornam imediatamente; as mudanças de tela chegam como um StatusEvent. Documentação completa →
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 }
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
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 } }
// 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 }
Visão geral da API
| KlugLayout.getInstance() | Retorna a instância única. |
| isSupported | Verdadeiro no Android e iOS. Falso nos demais; cada chamada é então uma operação nula. |
| setSensorLandscape() | Paisagem nos dois lados, girando junto com o dispositivo. Chame-o após stage.setAspectRatio(StageAspectRatio.LANDSCAPE). Android; no iOS, LANDSCAPE já permite os dois lados. |
| displayRotation | A rotação atual da tela em graus (0, 90, 180, 270), ou -1. |
| watchFold( stage ) | Começa a monitorar mudanças de dobra e de tela externa, também sem bloqueio de paisagem. No iOS, o stage é necessário para o iPhone Duo. |
| isFoldable | Verdadeiro em hardware dobrável: dobráveis Android (Android 11 ou posterior) e o iPhone Duo. |
| release() | Remove o bloqueio de paisagem, por exemplo quando o app muda para um layout de celular. Android; sem efeito no iOS. |
| deviceClass | A classe atual: "phone", "tablet" ou "cover"; "" enquanto desconhecida. No iOS, disponível após watchFold(stage) no iPhone Duo. |
| windowWidth / windowHeight | Tamanho da janela atual em pixels, acompanhando o dispositivo até a outra tela; -1 quando desconhecido. |
| safeInsetTop | Inset superior da tela atual em pixels: o recorte da câmera no Android (Android 9 ou posterior), a área segura superior no iOS; -1 quando desconhecido. |
| DEVICE_TYPE_CHANGED | Código de StatusEvent enviado a cada mudança de classe. |
Eventos
| deviceTypeChanged | phone · tablet · cover (cover: tela externa do Galaxy Z Flip, Android). Enviado após watchFold(stage), no Android também após setSensorLandscape(); somente nas mudanças. |
Compre o KlugLayout
Uma licença anual para um app AIR, com todas as atualizações por 12 meses. Após o pagamento, você recebe a extensão, a biblioteca ActionScript e a documentação por e-mail, normalmente em até um dia útil. Licença e termos
- Licença para um app AIR
- Todas as atualizações por 12 meses
- Sem suporte
- Licença para um app AIR
- Todas as atualizações por 12 meses
- Resposta por e-mail em até 7 dias
- Licença para um app AIR
- Todas as atualizações por 12 meses
- Resposta por e-mail em até 48 horas
Requisitos
| AIR SDK | 51.x (HARMAN) |
| Android | Android 6.0 (API 23) ou posterior; recorte da câmera a partir do Android 9 (API 28) |
| iOS | iOS 13 ou posterior; iPhone Duo testado com o AIR 51.4.1 |
| Permissões | Nenhuma |