iphone-duo-capacitor について
iphone-duo-capacitor は、iPhone Duo 向けに Capacitor アプリを調整する開発者向けのガイドです。WebView の制約を説明し、安全領域、サイズクラス、既存のネイティブブリッジプラグインを使った段階的な対応方法を紹介します。
主な機能
- 01WebView の折りたたみ認識の制約を説明
- 02非対称なセーフエリアに対応
- 03変化する寸法に合わせてレイアウト
- 04端末判定ではなくサイズクラスを使用
- 05既存の折りたたみ端末向けブリッジを紹介
活用シーン
- 01iPhone Duo 向け Capacitor アプリの調整
- 02セーフエリアによるレイアウト問題の調査
- 03折りたたみや Split View による寸法変化への対応
- 04ネイティブプラグインで折りたたみ状態を取得
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mirzaaghazadeh/ iphone-duo-skills --skill iphone-duo-capacitorインストール後、Claude Code で/iphone-duo-capacitorを入力して読み込まれたか確認します。
詳細
iPhone Duo 上的 Capacitor
まずはここから始めてください。そうしないと、午後の時間を無駄にすることになります。
WebKit 27.1 は Device Posture と Viewport Segments を実装していますが、どちらも Safari だけが設定できる実験的なフラグの背後にあります。
Capacitor アプリは、フラグを制御できない WKWebView で動作します。そのため、navigator.devicePosture、device-posture メディアクエリ、env(viewport-segment-*) 変数はすべて利用できません。一方、同じデバイスの Safari で同じページを開くと、これらを利用できます。あるものと決めつけずに機能を検出し、どちらも利用できない場合に備えてください。
つまり、このデバイスでは、Web プラットフォームだけでは折りたたみ状態を認識できません。ただし、重要な機能の大半は利用できます。2 つの段階に分けて対応しましょう。
第 1 段階 — 今すぐ利用可能、ネイティブコード不要
セーフエリアを信頼し、左右対称だと決めつけない
これが実際のバグにつながる要因です。iOS は画面の片側にバーを配置します。その側は端末の向きと読み取り方向によって変わります。
バーは実際のセーフエリアのインセットとして反映されます。27.1 シミュレーターでの測定値は env(safe-area-inset-right) の 84px で、アプリが垂直バーを表示しない設定にすると、再読み込みなしで即座に env(safe-area-inset-top) の 82px に移動します。そのため、ほとんどのレイアウトでは、4 辺すべてに適切な env(safe-area-inset-*) のパディングを設定するだけで十分です。
width - env(safe-area-inset-left) * 2 の形式の式は、このデバイスでは不具合の原因になります。
正しくサイズ変更に対応する
ウィンドウのサイズは、開くとき、閉じるとき、折りたたむとき、回転するとき、Split View を使うときに常に変わります。サイズは必要なときに読み取り、値をキャッシュするのではなく、コンテナークエリや %/fr によるレイアウトを優先してください。useEffect や ngOnInit で測定して保持した値は、数秒後には古くなります。
デバイス判定ではなく、サイズクラスを基準にする
iOS はこのデバイスをサイズクラスで扱います。外側のディスプレイは幅がコンパクトで、内側のディスプレイは幅がレギュラーです。ユーザーエージェント文字列や画面の向きではなく、与えられたサイズに応じて切り替えてください。内側のディスプレイは、対応する向きを尊重しないためです。
シミュレーターでの測定値は、横向きの内側のディスプレイが 951×669、外側のディスプレイが 466×678 です。
幅の広いディスプレイではナビゲーションを横に配置する
iOS が独自のタブバーやツールバーを垂直のレールに移動すると、画面下部に固定した HTML のタブバーは、ほかのすべてのネイティブアプリと並んだときに、未対応であることが目立ちます。内側のディスプレイではサイドレール、外側のディスプレイでは画面下部のバーを使うのが Web での相当する対応であり、ブレークポイントを 1 つ設けるだけで実現できます。
第 2 段階 — ネイティブ側の対応が必要
iPhone Duo 固有の機能は、ネイティブ側から渡されるまで Web ビューからは見えません。
| ネイティブ API(iOS 27.1) | Web ビューで必要となる理由 |
|---|---|
UIView の reservedRegions(kind:options:) | 折り目とカメラの位置を把握し、レイアウトで避けられるようにするため |
UIHingeInteraction | エフェクトや姿勢の判定に使う、連続的なヒンジ角度を得るため |
trait collection の verticalBarEdge | iOS がバーを移動した辺を把握し、独自の UI 要素の配置を合わせるため |
traitCollection のサイズクラス | ブレークポイントによる推測ではなく、iOS が実際に使うシグナルを得るため |
これらを自分で実装する前に知っておくとよいことが 2 つあります。平らにした状態のスマートフォンでは、折り目の領域は非アクティブとして報告されます。そのため、読み取るには options: .includeInactive が必要です。設定しないと、デバイスにヒンジがないと判断してしまいます。また、UIHinge.status の更新は遅延するため、折りたたみの途中では角度と一致しません。両方を取得できる場合は、角度を正しい値として扱ってください。
既存のブリッジを使う
@erkamyaman/capacitor-foldable
は、この機能をすでに実現している MIT ライセンスのプラグインです。さらに Device Posture と
Viewport Segments も補完するため、標準の CSS をアプリですぐに使えます。
npm install @erkamyaman/capacitor-foldable
npx cap sync
import { Foldable, installFoldablePolyfill } from '@erkamyaman/capacitor-foldable';
await installFoldablePolyfill();
const fold = await Foldable.getFoldState();
await Foldable.addListener('foldStateChange', (state) => layout(state));
ポリフィルは <html> に --fold-left、--fold-width などを設定するため、
グリッドのガターを推測ではなく、折り目の位置に正確に配置できます。同じビルドで、
androidx.window を通じた Android の折りたたみ式端末にも対応します。
詳しい情報は iphone-duo-capacitor-skillsにあります。 CSS のパターン、完全な API、Ionic 固有の情報、シミュレーターと Android エミュレーターでの テスト方法を紹介しています。
Ionic アプリ
Ionic の ion-tabs は HTML なので、ネイティブのバーが移動しても画面下部に残ります。
方法は 2 つあります。選択された側の iOS の端にタブバーをサイドピルとして配置する
スタイルシートを使う方法と、
@rdlabo/capacitor-native-ui
を使う方法です。後者は、既存の ion-buttons、ion-button、ion-back-button、
ion-tab-bar を UIKit と SwiftUI で描画します。元の要素、その状態、ハンドラーは
WebView 内にそのまま残ります。デバイスの状態を入力として使うため、2 つの方法は
競合せず、組み合わせて使えます。また、プラグインは独自のセットアップ手順にも記載されています。
オプションの @rdlabo/ionic-theme-ios27を
追加すると、iOS 27 のスタイルを適用できます。
実施すること(順番)
- 前提とする対称性がないか、安全領域に関するすべての式を監査します。ここで大半のバグを 解消できます。
- サイズをキャッシュするのをやめ、渡されたサイズに応じて処理を分岐します。
- 横長ディスプレイには、スマートフォン向けレイアウトを引き伸ばすのではなく、専用の レイアウトを用意します。
- プラグインを追加し、標準 API の機能検出を行うことで、同じビルドが API に対応した ブラウザーでも引き続き動作するようにします。
- その後で初めて、ヒンジ角度による効果を検討します。適切な移植において、これは最も 重要度の低い部分です。
ステップ 1〜3 にはネイティブコードが不要で、タブレットでのアプリの動作も同時に改善できます。 ステップ 4 だけが iPhone Duo 固有の対応であり、Xcode 27.1 シミュレーターなしではテストできません。
ネイティブ API の機能とその理由については、../iphone-duo-adaptive-layout/SKILL.md と
../iphone-duo-vertical-bars/SKILL.md をお読みください。コードはそのまま使えませんが、
設計上の考え方は直接応用できます。