Android 12対応 .NET MAUI スプラッシュ画面フルカスタム実装ガイド

Android 12以降のスプラッシュ画面仕様変更により、「アプリ独自のフルスクリーン画像を好きなだけ表示する」従来のやり方は使えなくなりました。特に.NET MAUIでAndroidアプリを作っていると、「OSスプラッシュは最小限にして、その直後に自前のリッチな画面を出したい」というニーズが強いはずです。本記事では、.NET MAUI(Android 12+)で“フルカスタム”なスプラッシュ画面を安全かつ実践的に実現する手順と考え方を、コード付きで詳しく解説します。

目次

.NET MAUI × Android 12以降でスプラッシュ画面がどう変わったか

まず前提として、Android 12以降ではOSがスプラッシュ画面を一元管理するようになりました。.NET MAUIだから特別というわけではなく、すべてのネイティブアプリがこの仕様に従う必要があります。

Android 12のスプラッシュ仕様のポイント

  • アプリ起動時に、OS側が必ず「システムスプラッシュ」を表示する
  • このシステムスプラッシュは表示時間をアプリ側で短くすることはできない
  • アプリができるカスタマイズは以下のみ
    • 中央に表示されるアイコン(ロゴ)
    • 背景色やウィンドウの背景
    • 終了アニメーション
  • 「フル画面の任意画像を長々と表示しておく」という旧来のやり方は不可

この仕様はAndroid OS側の制約であり、.NET MAUIやXamarin、Kotlin/Javaなどの技術スタックに関係なく共通です。そのため、 「OSスプラッシュの表示時間そのものを短縮する」ことはできません。

「やりたいこと」と「実際にできること」の整理

やりたいことAndroid 12以降での現実的な手段
OSスプラッシュの表示時間を短くしたい不可。OS管理のため変更できない
フルスクリーン画像を自由に表示したい.NET MAUI側で擬似スプラッシュページを作る
デザインを毎バージョン更新したいアイコン・背景はOSスプラッシュ、レイアウトやアニメーションは擬似スプラッシュで柔軟に変更
起動後の初期化(DI・設定読み込みなど)を進めたい擬似スプラッシュ表示中に非同期処理として実行
戻るボタンでスプラッシュに戻らないようにしたいナビゲーションスタックに積まず、Application.Current.MainPage を置き換える

結論として、Android 12+ で「フルカスタムなスプラッシュ画面」を実現したい場合は、 「OSスプラッシュ(最小限)+擬似スプラッシュページ(アプリ側)」の2段構成がベストプラクティスになります。

基本戦略:OSスプラッシュは最小限、演出は擬似スプラッシュへ

現代的な多くのアプリ(YouTube、各種SNSなど)も同じ考え方で実装されています。

  • OSスプラッシュ:ブランドカラー+アイコン程度の最小限の表示
  • アプリ側:ロゴアニメーションや背景イラスト、ローディングUIなど“見せたい演出”を持つページ

.NET MAUIでも同様に、「起動直後の MainPage をカスタムスプラッシュ専用ページにする」ことで、 OSスプラッシュ直後にフルカスタムな画面を表示することができます。

2段構成のイメージ

フェーズ画面実装箇所
フェーズ1OSスプラッシュ(システム管理)Androidのテーマ/MauiSplash設定
フェーズ2擬似スプラッシュ(カスタムページ).NET MAUIのContentPage(CustomSplashPageなど)
フェーズ3本来のメイン画面(AppShellやMainPage)Application.Current.MainPage を差し替え

次のセクションから、このフェーズ2〜3の実装方法を、.NET MAUIのコード例とともに解説していきます。

.NET MAUIで擬似スプラッシュページを作る

CustomSplashPage(擬似スプラッシュ)を作成する

まずは、起動直後に表示するための専用ContentPageを用意します。背景画像、ブランドロゴ、ローディング表示など、自由にレイアウトできます。

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             x:Class="YourApp.CustomSplashPage"
             BackgroundColor="Black">
  <Grid>
    <Image Source="splash_bg.png"
           Aspect="AspectFill"
           Opacity="0.9" />

    <StackLayout VerticalOptions="Center"
                 HorizontalOptions="Center"
                 Spacing="16">
      <Image Source="brand_logo.png"
             WidthRequest="160"
             HeightRequest="160" />

      <Label Text="読み込み中..."
             TextColor="White"
             FontSize="16"
             HorizontalTextAlignment="Center" />

      <ActivityIndicator IsRunning="True"
                         Color="White" />
    </StackLayout>
  </Grid>
</ContentPage>

ここではシンプルな例ですが、実際には以下のような要素を組み合わせることもできます。

  • Lottieアニメーション(アニメーションロゴ)
  • プログレスバーやステップ表示
  • バージョン情報や環境(開発/本番)のバッジ表示

App.xaml.cs で起動直後の MainPage を擬似スプラッシュにする

次に、アプリ起動時に最初に表示されるページを CustomSplashPage に設定します。

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        // 起動直後は擬似スプラッシュを表示
        MainPage = new CustomSplashPage();
    }
}

これで、OSスプラッシュが終わるとすぐに、.NET MAUI側の擬似スプラッシュページが表示されるようになります。

OnAppearingで初期化&本体ページに差し替える

擬似スプラッシュページが表示されたタイミングで、必要な初期化処理を行い、その完了を待ってから 本来の MainPage / AppShell に置き換えます。

public partial class CustomSplashPage : ContentPage
{
    private bool _isNavigated = false;

    protected override async void OnAppearing()
    {
        base.OnAppearing();

        if (_isNavigated)
        {
            // 二重実行ガード(OnAppearingが複数回呼ばれた場合に備える)
            return;
        }

        _isNavigated = true;

        // ここで必要な初期化を実行
        // 例: 設定読み込み、DIコンテナの構築、リモート設定取得など
        // await ServiceLocator.InitAsync();
        // await LoadRemoteConfigAsync();

        // 「最低でもこのくらいは見せておきたい」という場合だけ Delay を使う
        // 特に必要なければ Task.Delay は省略してOK
        // await Task.Delay(800);

        // 戻るボタンで擬似スプラッシュに戻れないよう、
        // ナビゲーションスタックに積まず MainPage を差し替える
        Application.Current.MainPage = new AppShell();
        // NavigationPage運用の場合:
        // Application.Current.MainPage = new NavigationPage(new MainPage());
    }
}

ここで重要なのは、PushAsync で遷移しないことです。もし次のように書いてしまうと、 Androidの戻るボタンで擬似スプラッシュページに戻れてしまいます。

// 非推奨:戻るボタンで擬似スプラッシュに戻れる
await Navigation.PushAsync(new MainPage());

このため、Application.Current.MainPage を丸ごと置き換える方式が推奨です。

初回起動だけ擬似スプラッシュを出したい場合

「毎回スプラッシュを見せると鬱陶しいので、インストール直後だけ表示したい」というケースも多いです。その場合は、 Preferences などにフラグを保存して制御します。

using Microsoft.Maui.Storage;

public partial class App : Application
{
    private const string FirstLaunchKey = "IsFirstLaunch";

    public App()
    {
        InitializeComponent();

        var isFirstLaunch = Preferences.Get(FirstLaunchKey, true);

        if (isFirstLaunch)
        {
            // 初回起動時のみ擬似スプラッシュを表示
            MainPage = new CustomSplashPage();
            Preferences.Set(FirstLaunchKey, false);
        }
        else
        {
            // 2回目以降は直接本体へ
            MainPage = new AppShell();
        }
    }
}

このようにすることで、初回だけリッチなウェルカム+スプラッシュ、2回目以降はすぐに本体画面、というユーザー体験も簡単に実現できます。

AppShell / NavigationPage を使う場合の考え方

.NET MAUIでは通常、AppShell を使って画面構成を作ることが多いですが、その場合も考え方は同じです。

  • Shell運用: 擬似スプラッシュは Shell とは別の単独ページとして実装し、初期表示だけすり替える
  • NavigationPage運用: 擬似スプラッシュをナビゲーションスタックに積まず、MainPage を置き換える方式を徹底する

いずれの場合も、「スプラッシュに戻れない」ナビゲーション設計を心がけると、ユーザー体験が自然になります。

OSスプラッシュを“ほぼ透明化”するワークアラウンド

ここまでの方法だけでも十分実用的ですが、「可能な限りOSスプラッシュの存在感を消したい」という要望もあるかもしれません。その場合、Androidのテーマを透過気味にすることで、 起動時に見えるのがほぼアプリ側レイアウトだけ、という状態に近づけることができます。

ただしこれはあくまでワークアラウンド(裏技寄り)であり、端末やダークテーマとの相性によってはチラつき等が出る可能性があるため、実運用前に十分な検証が必要です。

styles.xml に独自テーマを定義する

Platforms/Android/Resources/values/styles.xml に、透過を有効にしたテーマを定義します。

<?xml version="1.0" encoding="utf-8" ?>
<resources>
  <style name="MainTheme" parent="Maui.MainTheme.NoActionBar">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
  </style>
</resources>

ここで windowIsTranslucent を true にすることで、起動時のウィンドウを半透明にします。背景色も transparent を設定しておくと、よりアプリ側の描画が前面に出ているように見えます。

MainActivity の Theme を差し替える

続いて、MainActivity.cs で、このテーマを使用するように指定します。

[Activity(
    Theme = "@style/MainTheme",
    MainLauncher = true,
    ConfigurationChanges = ConfigChanges.ScreenSize
                           | ConfigChanges.Orientation
                           | ConfigChanges.UiMode
                           | ConfigChanges.ScreenLayout
                           | ConfigChanges.SmallestScreenSize
                           | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
}

これにより、「OSスプラッシュというより、アプリ自身が最初から描画されている」ような見え方に近づけることができます。

このワークアラウンドを使う際の注意点

  • OSのテーマとの相性(特にダークテーマ)によっては、背景がチラつく
  • メーカー独自カスタマイズ(Xiaomiなど)との組み合わせで描画タイミングに差が出ることがある
  • Androidのアップデートで挙動が変わる可能性がゼロではない

そのため、公式の推奨に従うのであれば、 「OSスプラッシュは基本どおり使い、演出はアプリ側ページ(擬似スプラッシュ)に寄せる」 運用が無難です。このワークアラウンドは、どうしても必要な場合にだけ採用し、対応端末を十分に検証するようにしてください。

.NET MAUIでのOSスプラッシュ設定の整理

擬似スプラッシュだけに集中しがちですが、OSスプラッシュ側も最低限整えておくと、起動体験がより洗練されます。.NET MAUIでは、アイコンやスプラッシュの設定は主に .csproj と Resources フォルダで行います。

.csproj での典型的な設定例

<MauiAppIcon Include="Resources\AppIcon\appicon.svg" />

<MauiSplashScreen Include="Resources\Splash\splash.svg"
                  Color="#000000"
                  BaseSize="128,128" />

この設定により、Android 12以降のOSスプラッシュに対しても、

  • 中央アイコン:splash.svg(またはアプリアイコン)
  • 背景色:Color="#000000" の色

が適用されます。OSスプラッシュは最小限のブランド表現だけに留めるのがポイントです。

OSスプラッシュと擬似スプラッシュの役割分担イメージ

項目OSスプラッシュ(Android 12+)擬似スプラッシュ(.NET MAUIページ)
ロゴ表示中央にシンプルなアイコンを表示ロゴ+テキスト+アニメーションなど自由
背景1色のブランドカラー画像、グラデーション、動画風アニメーションも可
表示時間OSが管理(短縮不可)アプリ側で制御(初期化完了まで/任意の秒数)
ローディング表示表示不可ActivityIndicator、プログレスバー等を自由に配置
ABテスト・デザイン変更難しい(ビルドし直しが前提)リモート設定で切り替えも可能

パフォーマンスとユーザー体験の最適化ポイント

UIスレッドをブロックしない

擬似スプラッシュ表示中の初期化処理は、可能な限り非同期(async/await)で実行し、UIスレッドをブロックしないようにします。

protected override async void OnAppearing()
{
    base.OnAppearing();

    // 重い処理は Task.Run で別スレッドへ
    await Task.Run(async () =>
    {
        await InitializeServicesAsync();
        await LoadCacheAsync();
    });

    Application.Current.MainPage = new AppShell();
}

UIスレッドを同期的にブロックしてしまうと、擬似スプラッシュ画面のアニメーションやActivityIndicatorが固まって見えるため、 「フリーズしたのでは?」という悪い印象を与えかねません。

「見せ時間」を必要以上に長くしない

ブランド演出のためにスプラッシュを長く見せたくなるかもしれませんが、ユーザーが本当に見たいのはアプリの中身です。

  • どうしても演出が必要な場合だけ Task.Delay を使う
  • できるだけ「初期化が終わったらすぐ本体へ」を心がける
  • 初回起動だけは少し長め、それ以降は短め、などの工夫も有効

復帰時に毎回スプラッシュを出さない設計

Androidでは、バックグラウンドからの復帰時にもOSスプラッシュが見える場合がありますが、擬似スプラッシュまで毎回出てくると煩わしく感じられます。

そのため、

  • 完全終了(プロセスが落ちた)時のみ擬似スプラッシュから開始
  • 一時停止からの復帰では、従来の画面に戻るだけ

という設計にしておくと、より自然な体験になります。前述の Preferences を使ったフラグ管理と併用すると良いでしょう。

iOS / Windows での考え方(おまけ)

本記事の主眼は「.NET MAUI × Android 12+」ですが、同じアプリをiOSやWindowsでも動かす場合の考え方も整理しておきます。

プラットフォームOS側スプラッシュカスタム演出の推奨方法
Android 12+OSが表示時間を管理、アイコン・背景・終了アニメのみ変更可能.NET MAUIの擬似スプラッシュページでレイアウトやアニメを実装
iOSLaunchScreen.storyboard / LaunchScreen.xib など。やはり表示時間はOS管理Android同様に、起動直後のページをスプラッシュ用にするのが定番
Windowsアプリマニフェスト側でのスプラッシュイメージ。表示時間はOS依存起動後すぐにMAUIのページでカスタム演出を表示

つまり、「起動時の演出はアプリ側の最初のページで行う」という設計は、マルチプラットフォームで共通して通用するアプローチです。.NET MAUIの強みを活かす意味でも、UIロジックを共通化した擬似スプラッシュページを持っておくと保守性が高まります。

実装チェックリスト

最後に、本記事で紹介した内容をベースに、.NET MAUI(Android 12以降)でフルカスタムなスプラッシュ画面を作る際のチェックリストをまとめます。

  • OSスプラッシュは最小限のブランド表現(アイコン+背景色)に抑えたか
  • 起動直後の MainPage を CustomSplashPage に設定したか
  • CustomSplashPage.OnAppearing で必要な初期化を 非同期に実行しているか
  • 初期化完了後に Application.Current.MainPage = new AppShell() などで置き換えているか
  • 戻るボタンで擬似スプラッシュに戻れない設計になっているか
  • 初回起動だけスプラッシュを出したい場合、Preferences等でフラグ管理しているか
  • (ワークアラウンドを使う場合)透過テーマを設定し、複数端末&ダークテーマでチラつきがないか検証したか
  • 重い処理をUIスレッドでブロックしていないか(Task.Run / async/awaitで分離)

Android 12以降では、従来のように「OSスプラッシュを好きなだけカスタムする」ことはできなくなりましたが、 逆に考えると、「OSスプラッシュは共通のミニマム演出、細かいブランド体験はアプリ側で自由に」という分業が明確になったとも言えます。

.NET MAUI であれば、この擬似スプラッシュページの実装を1つ用意するだけで、Androidはもちろん、iOSやWindowsにも同じコンセプトを展開できます。 本記事の手順とコード例をベースに、プロジェクトに合った“フルカスタム”なスプラッシュ体験をぜひ設計してみてください。

この記事を書いた人

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

コメント

コメントする

目次