iOS 18のiPadで.NET MAUI Shell上部にHomeボタン風の余白が出る原因と対策(CustomShellRenderer)

.NET 8 の .NET MAUI(Shell)アプリを iPad(iPadOS 18.2.1)で動かしたときだけ、全ページ上部に「Home」ボタンのような余白や表示が出てしまうことがあります。iPhone / Android では再現しないこの現象を、原因の考え方から iOS 専用カスタマイズでの回避策までまとめます。

目次

現象:iPad(iOS 18 / iPadOS 18)だけ全ページ最上部に「Home」ボタン風の余白が出る

まず症状を整理します。今回のポイントは「iPad だけ」「全ページで同様」「ShellContent の Title に見える文字列が出る(または空のボタンだけ残る)」というところです。

項目状況
発生端末iPad(iPadOS 18.2.1)
発生しない端末iPhone(同系 iOS 18 でも発生しないことが多い) / Android タブレット
影響範囲特定ページだけでなく、遷移先を含む全ページ上部に常時出る
見た目最上部に余白+「Home」などボタン風の表示(タップできそうな見た目)
関連しそうな設定AppShell.xaml の ShellContent Title="Home" に由来しているように見える
試しても改善しない例Shell.NavBarIsVisible="False" を AppShell / 各ページ / コードビハインドで設定しても変わらない
Title を消した場合文字は消えるが、ボタンっぽい領域(余白)が残ることがある

「Title を消しても枠だけ残る」という挙動は、単純にラベル文字列が表示されているのではなく、iOS 側で何らかの “コンテナ UI(ボタンの器)” が確保されてしまっている可能性を示唆します。

よくある誤解:NavBar を消したのに、なぜ上部の表示が消えないのか

MAUI の Shell で Shell.NavBarIsVisible="False" を設定すると、多くのケースでは「ナビゲーションバー(タイトルが表示される上部バー)」を非表示にできます。しかし、今回のように iPad(しかも iOS 18)だけで出る「ボタン風の余白」は、NavBar とは別経路で作られている UI であることがあります。

  • NavBar は「ページのナビゲーション(戻る、タイトル、ToolbarItems など)」の領域
  • 一方、Shell の構成(タブ/フライアウト/タイトル表示)と iPad のサイズクラス(Regular/Compact)によって、iOS 側で別の UI が組み立てられることがある
  • その UI が、結果として「ShellContent の Title が載ったボタン風の何か」に見える

つまり「NavBar を消したのに消えない」=設定が間違っている、というよりも、消しているもの(NavBar)と、表示されて困っているもの(iPad iOS 18 の Shell レイアウト由来 UI)が別物という整理が有効です。

原因の考え方:iPad の Regular サイズクラス+iOS 18 の新しい挙動で Shell の見た目が崩れる

iOS では画面の広さや向きによって “サイズクラス(Size Class)” が変わり、同じアプリでも iPhone と iPad で UI の組み立て方が変わります。iPad は基本的に横幅が広く、HorizontalSizeClass が Regular になりやすいのが特徴です。

.NET MAUI の Shell は、このサイズクラスや iPad というデバイス特性に合わせて「タブの出し方」「タイトルの扱い」「フライアウトの見せ方」などを iOS 側で調整します。ところが iOS 18(iPad)では、Shell が想定していないレイアウトパスに入りやすくなり、結果として以下のような現象が起こることがあります。

  • タブやタイトル領域の扱いが変化し、上部に “項目を表す UI” が追加されたように見える
  • その UI に ShellContent の Title が流れ込み、「Home」などがボタン風に表示される
  • Title を消しても UI の器(領域確保)が残るため、余白や空ボタンに見える
観点iPhone(多くは Compact)iPad(多くは Regular)
HorizontalSizeClassCompactRegular
Shell の UI ルート比較的シンプルな構成になりやすいよりリッチな構成(広い画面向け)になりやすい
今回の不具合の起点その UI ルートに入らず、問題が表面化しにくい特定の UI ルートで上部に余計な領域が出やすい

この種の「OS の新しい挙動 × UI フレームワークの分岐ロジック」で起きる問題は、アプリ側の XAML を少し変えても直らないことが多いです。そこで現実的な回避策として、iPad × iOS 18 のときだけ “サイズクラスを Compact として扱う” というアプローチが効きます。

回避策:iOS の Shell レンダラーをカスタマイズし、iPad(iOS 18 以上)だけ Compact 扱いにする

ここからが本題です。回避の狙いはシンプルで、iPad なのに iPhone 的な UI ルート(Compact 前提)で Shell を描画させることです。これにより、問題の起点となっている iPad Regular 側のレイアウト分岐を避けられます。

実装全体像

手順やること目的
MauiProgram.csiOS のみ Shell ハンドラー(レンダラー)を差し替える標準の Shell 描画をフックして、iOS の挙動を調整する
CustomShellRendereriPad かつ iOS 18+ のとき HorizontalSizeClass を Compact に上書きiPad Regular 前提の UI ルートを避け、上部の不要な領域を抑制する

MauiProgram.cs:iOS のみ Shell を差し替える

MauiProgram.cs の CreateMauiApp 内で、iOS のときだけ Shell を差し替えます。ポイントは「他プラットフォームに影響を出さない」ことです。

.ConfigureMauiHandlers(handlers =>
{
#if IOS
    handlers.AddHandler(typeof(Shell), typeof(CustomShellRenderer));
#endif
});

この設定によって、iOS 実行時に Shell の描画が CustomShellRenderer に切り替わります。

CustomShellRenderer:iPad × iOS 18+ だけ Compact を強制する

iOS プロジェクト側(例:Platforms/iOS 配下など)に CustomShellRenderer.cs を作成し、ShellItemRenderer に trait override を設定します。

#if IOS
using UIKit;
// ShellRenderer / ShellItemRenderer の名前空間はプロジェクト構成により異なるため、
// 既存の ShellRenderer を参照できる using を追加してください。

public class CustomShellRenderer : ShellRenderer
{
    protected override IShellItemRenderer CreateShellItemRenderer(ShellItem item)
    {
        var renderer = base.CreateShellItemRenderer(item);

        if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad
            && UIDevice.CurrentDevice.CheckSystemVersion(18, 0)
            && renderer is ShellItemRenderer shellItemRenderer)
        {
            // iPad でも Compact 扱いにすることで、iOS 18 iPad 固有の表示崩れを回避
            shellItemRenderer.TraitOverrides.HorizontalSizeClass = UIUserInterfaceSizeClass.Compact;
        }

        return renderer;
    }
}
#endif

この実装で狙っているのは「iPad でありながら、横幅のサイズクラスを Compact として Shell の描画パスを変える」ことです。結果として、全ページ上部に現れていた “Home ボタン風の余白” が抑制されるケースがあります。

実装のコツ:適用範囲を “必要最小限” にする

回避策は強力ですが、iPad でサイズクラスを変えると UI 全体の挙動も変わり得ます。そこで、条件をしっかり絞るのが重要です。

  • iPad のみに限定:UserInterfaceIdiom == Pad
  • iOS 18 以上のみに限定:CheckSystemVersion(18, 0)
  • Shell の該当レンダラーに限定:renderer is ShellItemRenderer

また、将来 iOS 19 以降で状況が変わった場合に備え、「18.x のみに適用する」などの範囲指定を行うこともできます。

if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad
    && UIDevice.CurrentDevice.CheckSystemVersion(18, 0)
    && !UIDevice.CurrentDevice.CheckSystemVersion(19, 0)
    && renderer is ShellItemRenderer shellItemRenderer)
{
    shellItemRenderer.TraitOverrides.HorizontalSizeClass = UIUserInterfaceSizeClass.Compact;
}

「OS 側・フレームワーク側で根本修正が入ったら回避策を外したい」という運用を考えるなら、こうした条件分岐は特におすすめです。

確認ポイント:本当に “ShellContent Title が原因に見える表示” なのかを切り分ける

見た目が「Home」だったとしても、アプリ内のどの Title が出ているかで対応方針が変わることがあります。Shell では似たプロパティが多いため、切り分けの観点を表にしておきます。

表示に関係しやすい要素設定場所用途今回の症状との関係
ShellContent TitleAppShell.xamlタブ項目名/ナビゲーション項目名に使われる「Home」と一致しているなら強く疑う
FlyoutItem TitleAppShell.xamlフライアウトの項目名フライアウト構成次第で上部に影響することがある
Page.Title各ページナビゲーションバー上のタイトルNavBar を消すと通常は見えなくなる
Shell.TitleViewAppShell.xamlナビゲーションバーに任意 UI を埋め込むiOS 18 iPad で期待通りにならないケースが出やすい

「Title を消すと文字だけ消えるが器が残る」という場合は、“Title が器を作っている” のではなく “器は別にあり、Title がその中の表示要素に流れ込んでいる”と考えると説明がつきます。今回のような trait override による回避は、この “器” を作っているレイアウト分岐自体を避けるための手段です。

再現手順を最小化して検証する

チーム開発や不具合切り分けでは「再現できる最小構成」を用意すると、原因がアプリ固有なのかフレームワーク/OS なのか判断しやすくなります。以下は検証の進め方の一例です。

ステップやること期待する観察
1.NET MAUI の Shell テンプレートを新規作成ベースライン(素の状態)を確認できる
2AppShell.xaml で ShellContent に Title を明示(例:Home)問題の表示が Title と紐づいているか確認できる
3iPadOS 18.2.1 実機(または該当シミュレータ)で実行iPad だけで上部に余白/ボタン風が出るか
4NavBarIsVisible を False にして変化を見るNavBar ではないことを確認できる
5CustomShellRenderer の trait override を適用して再実行症状が消える/軽減するかを確認できる

この手順で「最小構成でも再現する」なら、アプリ固有のレイアウトではなく、iOS 18(iPad)× MAUI Shell の組み合わせで起きている可能性が高くなります。

副作用と注意点:iPad を Compact 扱いにするトレードオフ

iPad を Compact 扱いにすると、意図しない UI 変化が起きる可能性があります。実際の影響はアプリの Shell 構成(Tabs / Flyout / 複数階層ナビゲーション)によって変わります。

起こり得る影響具体例対処・考え方
フライアウト表示方式の変化iPad で常時表示されていたサイドメニューが、オーバーレイ表示に変わる「iPad は常時サイドバーが欲しい」要件がある場合は要注意
タブの表示位置/見え方の変化タブが iPhone ライクな見た目に寄る今回の不具合回避が優先なら許容、UI 要件が厳しいなら別案検討
レイアウト全体のブレ横画面時に想定していた余白や表示密度が変わる影響が大きい場合は「該当画面だけ別ナビゲーション」に切り分ける

とはいえ今回の回避策は「iOS 18 iPad だけ」「必要なときだけ」に限定できるため、不具合による UX 破綻を止血する用途としては非常に実用的です。まずは影響範囲を確認し、問題が出る画面・端末・OS バージョンでのみ適用するのが現実解になりやすいです。

実装を安定させるためのチェックリスト

実装後に「直ったように見えるが別の画面で変」「デバッグビルドだけ挙動が違う」といった状況を避けるため、確認観点をチェックリスト化しておきます。

チェック項目確認方法理由
iPad(iOS 18)で上部の余白/ボタン風 UI が消える問題が出ていた画面を複数遷移して確認「初期ページだけ」「特定ルートだけ」などを見落とさないため
iPhone の見た目が変わっていない同一ビルドで iPhone 実機/シミュレータ確認条件分岐が漏れると全 iOS に影響するため
Android / Windows など他プラットフォームに影響しない#if IOS の範囲を確認ハンドラー差し替えが iOS 以外に波及しないため
横画面/縦画面での差分回転や Split View(可能なら)で確認サイズクラス関連は回転・分割で変化しやすい
ToolbarItems / TitleView を使っている画面ツールバーを持つ画面で表示確認上部 UI の分岐に関係しやすい

補足:この手の不具合は “アプリのミス” ではなく、OS / フレームワークの境界で起きやすい

iOS のメジャーバージョン更新(今回なら iOS 18 / iPadOS 18)は、サイズクラスやナビゲーション UI の内部実装が微妙に変わることがあります。MAUI の Shell は OS ネイティブのコンテナ(ナビゲーション、タブ、フライアウト等)を組み合わせて表示するため、OS 側の変更の影響を受けやすい領域です。

同様の症状や Shell のタイトル表示周り(TitleView を含む)については、コミュニティでも報告が出ることがあります。根本修正はフレームワーク側の更新で入ることが多いため、将来的には MAUI のアップデートで解消する可能性もあります。一方で、プロダクションアプリでは「修正を待つ」より先にユーザー影響を止めたい場面が多く、今回のような “限定的な trait override” は実務で効きやすい回避策です。

まとめ:iPad(iOS 18)限定の “Home ボタン風の余白” は ShellRenderer の trait override で止血できる

  • iPadOS 18 の iPad だけ、全ページ上部に「Home」ボタン風の余白が出る場合がある
  • Shell.NavBarIsVisible="False" で消えないなら、NavBar 以外の UI が作られている可能性が高い
  • 回避策として、iOS の ShellRenderer をカスタマイズし、iPad(iOS 18+)だけ HorizontalSizeClass を Compact に上書きする
  • 副作用(iPad の UI が iPhone 寄りになる)もあり得るため、OS バージョンや端末を絞って最小限に適用する

上部の余白がユーザー体験を大きく損ねるタイプの不具合は、放置すると離脱にも直結します。まずは限定的な回避策で安定稼働を優先しつつ、将来の MAUI 更新で根本解決できるタイミングが来たら条件分岐を外す、という運用が現実的です。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次