mcpField
I
iphone-duo-flutter

iphone-duo-flutter

github.com/mirzaaghazadeh開発250472 回インストール今日更新
リポジトリ

iphone-duo-flutter について

iPhone Duo向けにアプリを調整するFlutter開発者向けのガイドです。制約に基づくレイアウトと辺ごとのセーフエリア処理に加え、プラットフォームチャネルでネイティブの折り目情報を取得する方法を説明します。

主な機能

  1. 01制約に基づくウィンドウサイズ変更への対応
  2. 02辺ごとのセーフエリアパディング処理
  3. 03幅のブレークポイントによるナビゲーション切り替え
  4. 04プラットフォームチャネルで領域を照会しヒンジイベントを受信

活用シーン

  1. 01折りたたみやSplit View時のレイアウト修正
  2. 02ディスプレイに応じたナビゲーションバーとレールの切り替え
  3. 03折り目やカメラ領域を避けた操作ウィジェットの配置

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mirzaaghazadeh/iphone-duo-skills --skill iphone-duo-flutter

インストール後、Claude Code で/iphone-duo-flutterを入力して読み込まれたか確認します。

詳細

iPhone Duo での Flutter

まず、これを確認してください。さもないと、午後の時間を無駄にすることになります。

MediaQuery.displayFeatures は「Android でのみ値が設定される」とドキュメントに記載されています。

Flutter の折りたたみデバイス向け抽象化は、Android のヒンジを想定して作られています。iPhone Duo では、デバイスをどのように折りたたんでも 空のリスト が返されます。dual_screen パッケージ(TwoPane、hingeAngleEvents)も同様に、実際には Android 専用で、最後に公開されたのはおよそ 3 年前です。

そのため、Flutter ではこのデバイスの折りたたみ状態を標準で検知できません。ただし、本当に重要な機能のほとんどは利用できます。2 段階に分けて対応しましょう。

第 1 段階 — 今すぐ使える、ネイティブコード不要の方法

優れた移植に必要な作業の大半はこれでカバーでき、すべて純粋な Dart で実装できます。

サイズ変更に正しく対応する

iPhone Duo では、アプリのサイズが頻繁に変わります。開く、閉じる、折りたたむ、回転する、Split View に入るといった操作によるものです。Flutter がサイズ変更の処理を担いますが、レイアウトを固定値ではなく制約に基づいて構築する必要があります。

  • レイアウトの判断には LayoutBuilder とその BoxConstraints を使います。
  • ウィンドウサイズが必要な場合は、MediaQuery.of(context) ではなく MediaQuery.sizeOf(context) を使います。sizeOf/paddingOf アクセサーは、読み取るプロパティが変わった場合にのみ再ビルドするため、サイズがこれほど頻繁に変わる場合に重要です。
  • initState やフィールドにサイズをキャッシュしないでください。数秒も経たないうちに古い値になります。
左右非対称のセーフエリアに対応する

これは実際のバグにつながりやすいポイントです。iPhone Duo では、システムコントロールが 片側に 配置されるため、左右非対称なインセットになることがよくあります。どちら側になるかは、デバイスの向きや Split View のどちら側を使うかによって異なります。

MediaQuery.paddingOf(context) は、left、top、right、bottom がそれぞれ独立した EdgeInsets を返します。それぞれの値を使ってください。width - padding.left * 2 のような式は、このデバイスでは不具合の原因になります。

SafeArea ウィジェットはすでに 4 辺を個別に処理するため、独自に余白を設定するより優先して使ってください。背景を端まで広げる必要がある場合は、背景を SafeArea の外側に置き、操作可能な前景だけを内側に置きます。

ブレークポイントをサイズクラスの考え方に置き換える

iOS はこのデバイスをサイズクラスで扱います。外側のディスプレイは 幅がコンパクト、内側のディスプレイは 幅がレギュラー です。Flutter にはサイズクラスがないため、幅のブレークポイントに置き換えます。Material 3 のウィンドウサイズクラスは妥当な目安です(コンパクト < 600、ミディアム 600–840、エクスパンデッド ≥ 840 論理ピクセル)。

次の 2 つのルールに従ってください。

  • Platform.isIOS、デバイスモデルの文字列、MediaQuery.orientationOf ではなく、渡された 制約 に基づいて分岐します。内側のディスプレイは対応する向きを尊重しないため、向きは信頼できる判断材料ではありません。
  • コンテンツ が機能しなくなる幅を基準にブレークポイントを選び、コンパクト/レギュラーの分割が適切に導かれるか確認します。
アダプティブなコンテナーを優先する

広いレイアウトには NavigationRail、狭いレイアウトには NavigationBar を使う方法は、iOS がコントロールを側面に移動する標準の動作に相当する Flutter の手法です。内側のディスプレイにレール、外側のディスプレイにバーを使えば、自然に近い操作感になり、必要なブレークポイントも 1 つで済みます。

第 2 段階 — プラットフォームチャネルが必要な方法

iPhone Duo 固有の機能を Dart で利用するには、プラットフォームチャネルを介して橋渡しする必要があります。執筆時点では、iPhone Duo をサポートする Flutter リリースはまだありません。そのため、自分で実装することを想定し、作業を始める前にサポートが追加されていないか確認してください。

優先度の高い順に、橋渡しする価値のある機能を示します。

ネイティブ API(iOS 27.1)Dart で利用する利点
UIView の reservedRegions(kind:)コントロールを折り目や画面下カメラに重ねないようにする
UIHingeInteractionエフェクト用の連続的なヒンジ角度
traitCollection のサイズクラスブレークポイントによる推測ではなく、iOS が実際に使うシグナル
ブリッジの設計方法

単発のクエリ(現在の予約領域、現在のサイズクラス)には MethodChannel を使い、継続的な情報には EventChannel を使います。ヒンジ角度はライブストリームなので、MethodChannel では大量のメッセージが送られてしまいます。

iOS 側では、Runner ターゲットで FlutterViewController に FlutterMethodChannel と FlutterEventChannel を登録し、そのビューからネイティブ API を読み取ります。予約領域の API は UIView に属しており、FlutterViewController のビューが問い合わせる対象として適切です。Dart のレイアウトが実際に占有するのはそのビューだからです。

領域はプレーンなマップ({left, top, width, height, kind, active})としてシリアライズし、Dart 側で Rect を再構築できるようにします。ポーリングするのではなく、変更時に領域のリストを送信します。

すべてにガードを設けてください。折りたたみ式ではないデバイスではヒンジは常に nil であり、これらの API は iOS 27.1 より前には存在しません。同じ Flutter バイナリがすべての iPhone で動作するため、例外を投げるのではなく、「領域なし、ヒンジなし」にフォールバックする必要があります。

その後、Tier 1 と同じように使う

Dart に領域が届いたら、すでに構築した同じ制約ベースのレイアウトに渡します。分割領域(折り目)は、インタラクティブなウィジェットを配置しない場所を示します。遮蔽領域(カメラ)は、覆わないようにする場所を示します。特定のコントロールを領域の周囲に移動させるには、Stack と Positioned、またはカスタムの MultiChildLayoutDelegate を使うのが、通常は最もすっきりした方法です。

作業の順序

  1. LayoutBuilder の下でアプリがきれいにリサイズされるようにします。ほとんどのバグはここで解消されます。
  2. MediaQuery.padding のすべての使用箇所を調べ、左右対称のインセットを前提とした計算を確認します。
  3. 向きやプラットフォームのチェックを、制約ベースの分岐に置き換えます。
  4. レールとバーを使ったレイアウトに切り替え、内側のディスプレイが単に引き伸ばされたスマートフォンのレイアウトにならないようにします。
  5. アプリに折り目への対応が本当に必要な場合に限り、その後でチャンネルを作成します。

ステップ 1~4 で、Flutter アプリは iPhone Duo で自然に使える状態にかなり近づき、同時にタブレットやデスクトップでも改善されます。ステップ 5 だけが iPhone Duo 固有の作業であり、Xcode 27.1 シミュレーターなしではテストできない唯一の部分です。

ネイティブ API の実際の動作やその理由については、../iphone-duo-adaptive-layout/SKILL.md と ../iphone-duo-readiness/SKILL.md を参照してください。コード自体は異なりますが、設計上の考え方はそのまま活用できます。

コメント