.NET MAUIでAndroidアプリを動かすと、上下(または下側)に黒帯が出て「全画面にしたいのに余白が残る」ことがあります。実はこの現象は、システムバーが残っているケースと、Target SDK/AndroidManifestの不整合で互換表示(レターボックス)になっているケースに大別できます。原因の切り分けから、MainActivityの実装例と設定の直し方まで解説します。
よくある症状と「黒帯(黒線)」の正体
.NET MAUI(Android)で「全画面表示にしたいのに上下(または下側)に黒帯・黒線が出る」現象は、見た目が似ていても原因が違うことが多いです。対処を間違えると、MainActivityをいくら弄っても直らない、または特定の端末だけ再発するといった沼に入りやすいので、まずは黒帯の種類を整理します。
| 黒帯の見え方 | よくある状況 | 疑うべき原因 | 最初の一手 |
|---|---|---|---|
| 画面上部/下部に一定の黒い領域が出る。スワイプでバーが出たり消えたりする | ジェスチャーナビ/3ボタンナビで挙動が変わる。キーボード表示で余白が増減する | 原因A:ステータスバー/ナビゲーションバー(System Bars)が残っている、Insets制御ができていない | MainActivityでWindowInsetsControllerCompatを使い、SystemBarsを隠す(没入型) |
| アプリ起動直後(スプラッシュ画面の時点)から黒帯が出る。端末やエミュレーターで差がある | 古いエミュレーターはダメ、新しいエミュレーターはOKなど環境依存が強い | 原因B:Target SDK/AndroidManifest/SDK設定の不整合で互換表示(レターボックス)になっている | Target SDKを最新寄りにし、Min SDKだけ下げる。生成されたManifestで実際の値を確認する |
| 黒帯というより「ノッチ周辺」「角丸」「ジェスチャー領域」を避けているように見える | ノッチ付き端末、縦長端末、タブレットで目立つ | Display Cutout設定、最大アスペクト比、画面回転固定、リサイズ不可などの設定 | 追加チェック項目(後述)を確認する |
最短で切り分けるチェックリスト
修正コードを書く前に、次のチェックで原因Aか原因Bかをほぼ判定できます。ここで迷わないと、解決までが一気に早くなります。
| チェック項目 | 見え方/結果 | 判断 |
|---|---|---|
| 黒帯はスプラッシュ画面の時点で出ている? | 出ている | 原因B寄り(Activityより前の設定が疑わしい) |
| 画面下端をスワイプするとナビゲーションバーが一時表示される? | 表示される/消える | 原因A寄り(System Barsの制御で改善する可能性が高い) |
| 端末/エミュレーターのAPIレベルで再現が変わる? | 古い/新しいで挙動が変わる | 原因B寄り(Target SDKや互換モードの影響) |
| 黒帯部分に時計/電波/戻るボタンなどのUIが載っている? | 載っている | 原因A寄り(ステータスバー/ナビゲーションバーそのもの) |
| 黒帯部分は完全な真っ黒で、UIが一切ない(ただの余白)? | 余白のみ | 原因Bまたはテーマ/背景色の可能性(Aの「透明化」不足もあり得る) |
原因A:システムバーが残っていて“全画面化できていない”
Androidでの「全画面」は、単にレイアウトを画面いっぱいに広げるだけでは成立しません。ステータスバーやナビゲーションバーは、端末の操作性や安全性のために表示され続けることが多く、アプリ側がInsets(余白)を正しく扱わないと、コンテンツが「システムバーの外側」に留まって黒帯のように見えます。
ポイントは「Insetsの制御」+「System Barsの非表示」
- WindowCompat.SetDecorFitsSystemWindows(Window, false):コンテンツをシステムウィンドウに“合わせない”(=コンテンツを端まで伸ばせる)
- WindowInsetsControllerCompatでSystemBarsを隠す:ステータスバー/ナビゲーションバーを非表示にする
- SystemBarsBehaviorを設定:スワイプ時だけ一時表示できるようにする(没入型に近い使い心地)
MainActivity.cs の実装例(.NET MAUI / Android)
以下は、.NET MAUIの MainActivity : MauiAppCompatActivity で「没入型表示」を行う代表例です。起動直後のタイミングで一度適用し、必要ならフォーカス復帰でも再適用すると安定します。
using Android.App;
using Android.OS;
using AndroidX.Core.View;
namespace YourAppNamespace;
[Activity(
Theme = "@style/Maui.SplashTheme",
MainLauncher = true,
ConfigurationChanges =
Android.Content.PM.ConfigChanges.ScreenSize |
Android.Content.PM.ConfigChanges.Orientation |
Android.Content.PM.ConfigChanges.UiMode |
Android.Content.PM.ConfigChanges.ScreenLayout |
Android.Content.PM.ConfigChanges.SmallestScreenSize)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
ApplyImmersiveMode();
}
public override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
if (hasFocus) ApplyImmersiveMode();
}
void ApplyImmersiveMode()
{
// 1) コンテンツをシステムバー領域まで伸ばす(Edge-to-edge)
WindowCompat.SetDecorFitsSystemWindows(Window, false);
// 2) System Bars を非表示にする(没入型)
var controller = WindowCompat.GetInsetsController(Window, Window.DecorView);
if (controller is null) return;
controller.Hide(WindowInsetsCompat.Type.SystemBars());
// 3) 必要時だけスワイプで一時表示できる挙動にする
controller.SystemBarsBehavior =
WindowInsetsControllerCompat.BehaviorShowTransientBarsBySwipe;
}
}
「黒帯」というよりステータスバー/ナビゲーションバーの背景が黒く見えているだけなら、隠す代わりに透過させる(または色を指定する)アプローチも有効です。ただし、端末やAndroidバージョンで見え方が変わりやすいので、まずは上の手順で「本当に全画面化できているか」を確認するのが安全です。
黒帯が“戻る”ときの考え方
Androidは、画面回転・キーボード表示・ダイアログ表示・別アプリから戻るなどのタイミングでSystem Barsの状態が変わることがあります。その結果、起動時は消えても操作中に黒帯が復活する場合があります。
このときは、上記のように OnWindowFocusChanged で再適用するか、アプリの状態遷移に合わせて(例:OnResume)再適用することで安定します。逆に、常にSystem Barsを消すのがUX的に厳しいアプリ(フォーム入力中心など)では、「隠す」ではなく「色/透明度を調整して違和感を減らす」方が現実的な場合もあります。
テーマ側で「黒く見える」原因を潰す
System Barsを消さない場合や、端末によってはバー領域に背景色が塗られて「黒帯」に見える場合があります。これはThemeの設定で改善できることがあります。
<!-- Platforms/Android/Resources/values/styles.xml の例 -->
<resources>
<!-- スプラッシュ用テーマ(起動直後の黒帯/チラつきもここが関係します) -->
<style name="Maui.SplashTheme" parent="Theme.SplashScreen">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<!-- 通常表示用テーマ -->
<style name="Maui.MainTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
</resources>
注意点として、透過にした場合はコンテンツがバー領域に被るため、画面上部/下部のUIが見切れないようにレイアウト側でInsetsを考慮する必要があります。「全画面=何も考えなくていい」ではなく、全画面にした分だけUI配置の設計が必要、というイメージです。
原因Aでよくある落とし穴
| 落とし穴 | 症状 | 対策 |
|---|---|---|
| 古いフルスクリーンAPI(Flags)だけで頑張る | 一部端末/ジェスチャーナビで効かない、すぐ戻る | WindowInsetsControllerCompat(AndroidX)を優先し、必要ならフォーカス復帰で再適用 |
| SetDecorFitsSystemWindowsの設定がない | バーを消してもコンテンツが端まで伸びない | SetDecorFitsSystemWindows(false) を併用してEdge-to-edgeにする |
| テーマのstatusBarColor/navigationBarColorが黒のまま | 「バーが残って黒帯に見える」 | テーマで色を指定(透明/アプリ色など)。ただしコンテンツの見切れに注意 |
| フォーカス復帰時に再適用していない | 一度は消えるが、戻る操作や画面回転で再出現 | OnWindowFocusChanged/OnResume等で再適用する |
原因B:“MainActivityが動く前から”黒帯が見える/端末・エミュレーターで挙動が違う
こちらは、コードでSystem Barsを制御する以前に、アプリが互換モード(レターボックス)のような表示になっているパターンです。特に「Android 5.0(API 21)をターゲットしていた」「Android 10以上のエミュレーターだとおかしい(または逆)」のように、環境差があるときは原因Bを強く疑います。
なぜTarget SDKが古いと黒帯が出るのか
Androidは、新しい画面仕様(縦長ディスプレイ、ノッチ、角丸、ジェスチャーナビ、マルチウィンドウなど)に対して、古いTarget SDKのアプリが安全に動くように互換動作を行うことがあります。その一環として、アプリの表示領域を意図的に狭めたり、特定領域を使わせないことで、結果的に黒帯(余白)が発生することがあります。
つまりこのケースは、「UIを隠す/透過する」の問題ではなく、「アプリが新しいOSで正しい前提(Target SDK)として扱われていない」のが本質です。
まず確認するべきは「生成されたAndroidManifest.xml」
.NET MAUIは、プロジェクト内の設定(.csprojや手動で追加したAndroidManifestなど)からビルド時に最終的なManifestを生成します。あなたが編集しているAndroidManifest.xmlと、実際に端末へ入るManifestがズレていることもあります。
- ビルド後に
obj/Debug/net8.0-android/AndroidManifest.xml(構成によりReleaseなど)を開いて、targetSdkVersionとminSdkVersionを確認する - 「手動のAndroidManifestを置いている場合」は、
<uses-sdk>の指定が古く固定されていないか確認する
推奨方針:Target SDKは最新寄り、Min SDKで下限を担保
古いOSをサポートしたい場合でも、基本はMin SDKで下限を決め、Target SDKはできるだけ新しく保ちます。これにより、新しいAndroidで互換モードに入るリスクを下げられます。
| 項目 | 役割 | おすすめ | よくある失敗 |
|---|---|---|---|
| Min SDK(minSdkVersion) | インストールできる最小OS | 要件に合わせて下げる(例:Android 5.0相当のAPI 21) | 必要以上に上げてしまい、古い端末が切り捨てになる |
| Target SDK(targetSdkVersion) | アプリが想定するOSの挙動 | 最新寄り(例:検証しているAndroidの主要バージョン相当) | Min SDKと混同して低く固定し、互換動作でレイアウトが崩れる |
| エミュレーターAPIレベル | 検証環境 | Min/Target/実運用想定に合わせて複数用意 | 検証したいOSとズレたAVDだけで判断してしまう |
.csprojで設定する例(.NET MAUI)
MAUIプロジェクトでは、AndroidのMin/Targetをプロジェクト設定で管理できます。チーム開発やCIでもブレにくいので、まずはここを整えるのが手堅いです(プロパティ名は利用している.NET/Androidワークロードで差が出る場合があります)。
<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<!-- 最小対応(例:Android 5.0 / API 21) -->
<AndroidMinSdkVersion>21</AndroidMinSdkVersion>
<!-- ターゲットは最新寄り(例:API 34) -->
<AndroidTargetSdkVersion>34</AndroidTargetSdkVersion>
</PropertyGroup>
もしプロジェクト内にAndroidManifest.xmlを手動で置いているなら、<uses-sdk> でTargetを古く固定していないか要注意です。MAUI側の設定とManifest側の設定が食い違うと、「実機はOKだがエミュレーターはNG」のようなブレが起きやすくなります。
AndroidManifest.xmlを自前管理している場合の注意
手動のAndroidManifestに以下のような指定がある場合、意図せず古いTarget SDKとして扱われることがあります。
<!-- 例:Targetが古く固定されてしまうパターン -->
<uses-sdk
android:minSdkVersion="21"
android:targetSdkVersion="21" />
この状態でAndroid 10以降のエミュレーター/実機に入れると、互換動作の影響が強く出て「黒帯が消えない」「端末差が出る」といった現象が起きやすくなります。修正方針は次のどちらかです。
- Manifestの<uses-sdk>指定を削除し、.csproj側で一元管理する
- Manifestを残すなら、Min/Targetをプロジェクト設定と同じ値に揃える
エミュレーターでの再現性を上げるコツ
黒帯問題は、検証環境が揃っていないと「直ったのか偶然なのか」が判断しづらいです。おすすめは、APIレベル別にAVDを用意して、どの軸で差が出るかを明確にすることです。
| 検証対象 | AVD例 | 見るべきポイント |
|---|---|---|
| Min SDK相当 | API 21〜23 | 起動できるか、画面サイズやノッチがない環境でのベース動作 |
| 現行に近い | API 29〜30(Android 10〜11) | ジェスチャーナビ、Insets、スプラッシュから黒帯が出ないか |
| 最新 | API 33〜34 | ターゲット互換、Display Cutout、UIの見切れや余白 |
また、最速の切り分けとして新規のMAUIプロジェクトを作り、同じエミュレーターで表示が正常かを確認するのも有効です。新規プロジェクトで問題が再現しないなら、既存プロジェクトのManifest/テーマ/ターゲット設定に原因が寄っている可能性が高くなります。
それでも黒帯が消えないときの追加チェック
原因A/Bを潰しても残る場合は、端末形状やアクティビティ設定が関係していることがあります。特にノッチ端末・縦長端末・タブレットで目立ちます。
| 追加チェック | ありがちな設定 | 起こり得る症状 | 対処の方向性 |
|---|---|---|---|
| Display Cutout(ノッチ) | cutout領域を使わない既定 | 上端に余白が残る/見切れ回避で黒帯に見える | テーマで android:windowLayoutInDisplayCutoutMode を検討(ただしUI設計とセット) |
| 画面回転固定・リサイズ不可 | screenOrientation固定、resizeableActivityをfalse | 一部端末でレターボックス(余白) | 固定が必要か再検討。必要なら端末差を前提にレイアウト調整 |
| スプラッシュテーマと本テーマの差 | SplashThemeは黒背景、本テーマは別色 | 起動直後だけ黒帯に見える/切り替わりでチラつく | SplashThemeとMainThemeのSystem Bar設定を揃える |
| 背景色が黒のまま | ページ背景、Window背景が黒 | 「余白」が黒帯に見える | 一時的に背景色を派手な色にして、余白の正体(どのレイヤーか)を特定する |
実務で迷わないためのおすすめ手順
最後に、現場で再発しやすい「黒帯問題」を短時間で潰すための手順をまとめます。上から順にやると、遠回りしにくいです。
- 黒帯がスプラッシュ時点で出るかを確認し、原因A/Bの当たりを付ける
- 原因A疑いなら、MainActivityでInsets制御+SystemBars非表示を入れて挙動を見る
- 同時に、テーマのstatusBarColor/navigationBarColorを確認し、黒く見えているだけの可能性を潰す
- 原因B疑いなら、生成されたAndroidManifestでMin/Targetを確認し、Target SDKを最新寄りに修正する
- APIレベル別にAVDを用意し、どの条件で再現するかを表にして記録する(端末差の説明がしやすくなる)
まとめ
.NET MAUI(Android)の「全画面なのに黒帯が出る」問題は、システムバーが残っている(原因A)のか、Target SDK/Manifestの不整合で互換表示になっている(原因B)のかで、最適解が変わります。まずはスプラッシュ時点の挙動と生成Manifestで切り分け、AならInsets+SystemBars制御、BならTargetを最新寄りに直す――この順で進めれば、コードと設定の両面から最短距離で解決できます。

コメント