「色付きのPNGを指定したのに、通知の“小さなアイコン(small icon)”が灰色(単色)で出てしまう」。.NET MAUI/Androidでよく遭遇する疑問です。本記事はその原因を“仕様”から噛み砕いて説明し、実務で取るべき正攻法(white単色のsmall icon+large icon/スタイル活用/カスタムレイアウト)を、コードと作業手順・チェックリスト付きでまとめます。
結論:small icon はアルファ(透明度)だけを見る「単色マスク」。色を維持する方法はない
Androidの通知における small icon(ステータスバーや通知シェード左端に表示される24×24dp相当の小アイコン)は、画像のアルファ(透明度)情報だけを読み取り、OS側が単色で塗りつぶして描画します。したがって、SetSmallIcon(Resource.Drawable.ic_push_notification_solid) のように黄色のPNGを渡しても、通知上では白〜グレーのモノクロに変換されます。これはAndroid 5.0(API 21)以降で一貫した挙動であり、コードや設定で「small iconをカラー表示」にするトグルは存在しません。
ではどう見せるか:業務で使える3つの正攻法
| 目的 | 対応方法 | 備考 |
|---|---|---|
| 通知の規定位置に正しく小アイコンを出したい | 透過背景+白一色のPNGまたはVectorDrawableを用意し、SetSmallIcon()に指定 | 塗りは白、背景は完全透過。線は太すぎず(1〜2dp目安)。 |
| ブランドカラーや写真を見せたい | SetLargeIcon()でカラー画像を渡す/BigPictureStyleやカスタム通知レイアウトを使う | large icon/ビッグピクチャはカラーで出せる。 |
| 種類ごとの違いを色で演出したい | SetColor()(および通知チャンネルの色)でアクセントを付ける | small icon自体は白のまま。通知ヘッダーやシェード背景に色が乗る。 |
.NET MAUI/NotificationCompat での実装例(最小構成)
using Android.App;
using Android.Graphics;
using Android.OS;
using AndroidX.Core.App;
const string CHANNEL_ID = "local_default";
void ShowNotification(Context context)
{
var manager = NotificationManagerCompat.From(context);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channel = new NotificationChannel(
CHANNEL_ID, "Default", NotificationImportance.Default)
{
Description = "Local notifications"
};
// アクセント(small iconの色ではない)
channel.EnableLights(true);
channel.LightColor = Color.Yellow;
channel.EnableVibration(true);
var sys = (NotificationManager)context.GetSystemService(Context.NotificationService);
sys.CreateNotificationChannel(channel);
}
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
// small icon は白単色。drawable名はすべて小文字・アンダースコア
.SetSmallIcon(Resource.Drawable.ic_notification_white)
// large icon はカラーOK
.SetLargeIcon(BitmapFactory.DecodeResource(
context.Resources, Resource.Drawable.ic_push_notification_solid))
.SetContentTitle("タイトル")
.SetContentText("本文")
.SetAutoCancel(true)
// アクセントカラー。通知全体の強調に使われる(small iconは白のまま)
.SetColor(new Color(0xFF, 0xC1, 0x07)); // #FFC107
manager.Notify(1001, builder.Build());
}
LocalPushNotification(.NET MAUI向けローカル通知プラグイン)を使う場合
プラグインを利用している場合も考え方は同じです。small iconには白単色のdrawable名、large iconにはカラーのdrawable名を指定します。
using Plugin.LocalNotification;
var request = new NotificationRequest
{
NotificationId = 1002,
Title = "タイトル",
Description = "本文",
Android = new AndroidOptions
{
// small icon(白単色)
IconSmallName = new AndroidIcon("ic_notification_white"),
// large icon(カラーOK)
IconLargeName = new AndroidIcon("ic_push_notification_solid"),
ChannelId = "local_default"
}
};
await LocalNotificationCenter.Current.Show(request);
※プラグインのプロパティ名はバージョンで差異がありますが、smallは白単色・largeはカラーという原則は変わりません。
small icon のアセット作成ガイド(PNG/VectorDrawable)
作成ルール(実務の要点)
- キャンバスは 24×24dp(mdpiなら24×24px)。
- 塗りは白一色(#FFFFFFFF)。背景は完全透過。
- グリフは最大18dp程度に収め、上下左右に約3dpの余白を取ると視認性が安定。
- アンチエイリアス前提のなめらかなエッジ、細線は1〜2dpを目安に。
- リソース名はすべて小文字+アンダースコア(例:
ic_notification_white)。
解像度(density)別の推奨ピクセルサイズ
| 用途 | mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi |
|---|---|---|---|---|---|
| small icon(キャンバス) | 24×24 | 36×36 | 48×48 | 72×72 | 96×96 |
| large icon(キャンバス) | 48×48 | 72×72 | 96×96 | 144×144 | 192×192 |
VectorDrawable でsmall iconを定義(API 21+)
VectorDrawableを使うと密度ごとのPNGを用意せずに済みます(small iconは単色である点に注意)。
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2L2,22h20L12,2z" /> <!-- サンプル:三角形 -->
配置場所(.NET MAUIの単一プロジェクト)例:
Platforms/Android/Resources/drawable-anydpi-v24/ic_notification_white.xml(ビルドアクション:AndroidResource)- PNGで用意するなら
Platforms/Android/Resources/drawable-xxxhdpi/...などdensity別に配置します。
「色を見せたい」を叶える実装パターン
1) Large Icon を併用
smallは白、largeでカラーを見せます。通知が展開されるとlargeが目立ちます。
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetLargeIcon(BitmapFactory.DecodeResource(
context.Resources, Resource.Drawable.ic_push_notification_solid))
.SetContentTitle("新着メッセージ")
.SetContentText("本文…");
2) BigPictureStyle でビジュアル訴求
var picture = BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.banner_hero);
var style = new NotificationCompat.BigPictureStyle()
.BigPicture(picture)
.BigLargeIcon(null); // 展開時はlarge iconを隠してビジュアルに集中
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetLargeIcon(BitmapFactory.DecodeResource(context.Resources, Resource.Drawable.ic_push_notification_solid))
.SetStyle(style)
.SetContentTitle("本日のおすすめ")
.SetContentText("詳細はこちら");
3) カスタム通知レイアウト(RemoteViews)
より柔軟に色付き画像やブランドカラーを使いたい場合は、カスタムレイアウトを検討します。collapsed/expanded用のRemoteViewsを用意し、そこにカラー画像や装飾を配置します。small icon自体はルール通り白単色のままです。
var collapsed = new RemoteViews(context.PackageName, Resource.Layout.notification_collapsed);
var expanded = new RemoteViews(context.PackageName, Resource.Layout.notification_expanded);
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetCustomContentView(collapsed)
.SetCustomBigContentView(expanded)
.SetStyle(new NotificationCompat.DecoratedCustomViewStyle());
※一部OEMやOSバージョンでレイアウトの余白・行間が異なるため、複数端末での検証が重要です。
アクセントカラーの使い方(SetColor() と通知チャンネル)
NotificationCompat.Builder.SetColor(Color)… 通知内の強調(ヘッダーやアクションの背景など)に影響。small iconの色は変わらない。- Android 8.0+は通知チャンネル単位の設定が優先される場面があるため、色の設計は「チャンネル=文脈」単位で行うのが吉。
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channel = new NotificationChannel(
"news_alert", "ニュース", NotificationImportance.High)
{
Description = "ニュース速報"
};
channel.EnableLights(true);
channel.LightColor = Color.ParseColor("#FF5252"); // チャンネルのアクセント
var sys = (NotificationManager)context.GetSystemService(Context.NotificationService);
sys.CreateNotificationChannel(channel);
}
var builder = new NotificationCompat.Builder(context, "news_alert")
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetColor(Color.ParseColor("#FF5252"));
MAUIプロジェクトでのリソース配置とビルド設定
- 通知アイコンはAndroid固有のリソースのため、
Platforms/Android/Resources/配下に配置。 - ビルドアクションはAndroidResource(PNG/XMLいずれも)。
- リソース名は小文字+アンダースコア。大文字・ハイフンは不可。
- Adaptive Icon(アプリアイコン用)をsmall iconに流用しない。通知では単色のマスクが必要。
よくある落とし穴と対処
| 症状 | 原因 | 対処 |
|---|---|---|
| アイコンが薄くて見えにくい | 線が細すぎ/余白が広すぎ | 線幅1.5〜2dp・余白3dp目安で描き直す。輪郭をはっきりさせる。 |
| 黒背景でつぶれる/白背景で埋もれる | OSのテーマや通知シェードの色味による | 白単色+適切な余白に統一。色表現はlarge/スタイルで行う。 |
| VectorDrawableが表示されない | 配置先やビルドアクションが誤り | drawable-anydpi-v24配下に置き、AndroidResourceに設定。 |
| 一部端末でサイズが不自然 | PNGの密度別リソースが不足 | mdpi〜xxxhdpiまで用意 or VectorDrawableに統一。 |
| 色が付かない(付けたい) | 仕様 | smallは単色。色はSetLargeIcon()/BigPicture/カスタムで。 |
デザイン指針(現場のコツ)
- 意味が一目で分かる形状:ベル=通知、雲=アップロード、盾=セキュリティなど。
- 線と面の対比:白塗りの面を主体に、細線は最小限。小サイズで潰れない形。
- 余白の均等:左右非対称だと小ささの影響で傾いて見える。
- バリエーション設計:イベント種別ごとにsmall iconの「形」を変える(色で区別は不可)。
「APIやOSバージョン違い」で知っておくと楽になるポイント
- Android 5.0(API 21)以降:small iconはアルファマスク+単色描画。以降のバージョンでもこの原則は維持。
- Adaptive Icon/monochromeレイヤー:これはアプリアイコン(ホーム画面)の話で、通知small iconとは無関係。
- Dynamic Color(Material You):通知UIの色合いには影響し得るが、small icon自体がカラー化されることはない。
テストのやり方(品質を落とさない運用)
- ライト/ダークテーマを切り替え表示を確認。
- 最小〜最大解像度(mdpi〜xxxhdpi)エミュレータで視認性をチェック。
- 通知の展開・非展開でレイアウト崩れがないか(large/BigPicture/カスタム)。
- 複数チャンネルで
SetColor()の効き方を比較。 - 長文タイトル・本文・多ボタン配置時の折返し挙動を検証。
運用設計:通知チャンネルとアイコンの関係
通知の設計は「small=白単色(形で識別)」「large/スタイル=色や写真で訴求」という役割分担を前提に、チャンネル(用途)ごとにアイコンとアクセントカラーのペアを定義すると運用が安定します。たとえば「メッセージ」「システム」「キャンペーン」の3種類を用意し、それぞれでsmallの形とSetColor()の色を変える、といった設計です。
実務で使えるテンプレート(コピペ可)
通知ビルダー(.NET MAUI/Android)
public static class Notifier
{
const string ChannelId = "app_default";
public static void EnsureChannel(Context context)
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O) return;
var channel = new NotificationChannel(
ChannelId, "一般通知", NotificationImportance.Default)
{
Description = "アプリの一般通知"
};
channel.EnableLights(true);
channel.LightColor = Android.Graphics.Color.ParseColor("#2962FF");
channel.EnableVibration(true);
var sys = (NotificationManager)context.GetSystemService(Context.NotificationService);
sys.CreateNotificationChannel(channel);
}
public static void SendBasic(Context context, string title, string message)
{
EnsureChannel(context);
var builder = new NotificationCompat.Builder(context, ChannelId)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetContentTitle(title)
.SetContentText(message)
.SetAutoCancel(true)
.SetColor(Android.Graphics.Color.ParseColor("#2962FF"));
NotificationManagerCompat.From(context).Notify(Random.Shared.Next(), builder.Build());
}
public static void SendWithLargeIcon(Context context, string title, string message, int largeIconRes)
{
EnsureChannel(context);
var builder = new NotificationCompat.Builder(context, ChannelId)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetLargeIcon(BitmapFactory.DecodeResource(context.Resources, largeIconRes))
.SetContentTitle(title)
.SetContentText(message)
.SetAutoCancel(true);
NotificationManagerCompat.From(context).Notify(Random.Shared.Next(), builder.Build());
}
public static void SendBigPicture(Context context, string title, string message, int pictureRes)
{
EnsureChannel(context);
var picture = BitmapFactory.DecodeResource(context.Resources, pictureRes);
var style = new NotificationCompat.BigPictureStyle()
.BigPicture(picture)
.BigLargeIcon(null);
var builder = new NotificationCompat.Builder(context, ChannelId)
.SetSmallIcon(Resource.Drawable.ic_notification_white)
.SetStyle(style)
.SetContentTitle(title)
.SetContentText(message)
.SetAutoCancel(true);
NotificationManagerCompat.From(context).Notify(Random.Shared.Next(), builder.Build());
}
}
アセット配置の雛形(プロジェクト構成)
MyMauiApp/
├─ Resources/
│ └─ Images/ <-- 画面用の通常画像(通知smallには使わない)
├─ Platforms/
│ └─ Android/
│ └─ Resources/
│ ├─ drawable-anydpi-v24/
│ │ └─ ic_notification_white.xml <-- small icon(白単色Vector)
│ ├─ drawable-xxxhdpi/
│ │ └─ ic_push_notification_solid.png <-- large icon(カラー)
│ └─ layout/
│ ├─ notification_collapsed.xml
│ └─ notification_expanded.xml
FAQ
Q. small iconを黄色にしたい。非推奨でも良いので方法は?
A. small iconは仕様で単色化されます。回避策はありません。黄色を見せたい場合は SetLargeIcon()・BigPictureStyle・カスタムレイアウトで表現します。
Q. SetColor()でsmallの色を変えられませんか?
A. 変えられません。SetColor()は通知のアクセントで、small icon(アルファマスク)の描画色には直接影響しません。
Q. Adaptive Iconのmonochromeレイヤーは使えますか?
A. それはアプリアイコン(ホーム画面)用です。通知のsmall iconとは別物です。
Q. .NET MAUIで画像をResources/Imagesに置いたが参照できません
A. 通知アイコンはAndroid固有のリソース(Platforms/Android/Resources/drawable...)として配置し、ビルドアクションをAndroidResourceに設定します。
Q. VectorDrawableの色をテーマに合わせて変えられますか?
A. small iconはOS側で単色化されるため、テーマ色での塗り替えは発生しません(小アイコンとしては常にモノクロ)。
チェックリスト(導入前・リリース前に確認)
- small iconは白単色・透過背景・適切な余白か。
- densityごとのPNG、またはVectorDrawableで網羅できているか。
- 通知チャンネルが用途ごとに分かれ、アクセント色が設計されているか。
- large iconやBigPictureで色表現を補えているか。
- ライト/ダーク、各density、主要OEMスキンで視認性を確認したか。
サンプル:色付きPNGを渡しても灰色になる再現
以下のコードは、SetSmallIcon()にカラーPNGを指定していますが、通知上ではOSにより白〜グレーで描画されます(仕様)。
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_push_notification_solid) // 黄色PNGを渡しても…
.SetContentTitle("色は付かない")
.SetContentText("small iconはOSが単色で描画します。");
これを次のように直せば、意図通りの表示になります。
var builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_notification_white) // 白単色
.SetLargeIcon(BitmapFactory.DecodeResource(
context.Resources, Resource.Drawable.ic_push_notification_solid)) // カラーはlargeへ
.SetContentTitle("正しい使い分け")
.SetContentText("small=白、large/スタイル=色付きで訴求。");
まとめ
Androidの通知におけるsmall iconは、「アルファだけを読むマスク」+「OSの単色塗り」という厳格な仕様が基本です。色を維持させる回避策は存在しません。代わりに、smallは白単色で形の識別、large/BigPicture/カスタムで色表現という役割分担に切り替えましょう。.NET MAUIでも、リソース配置(AndroidResource)、ビルド設定、通知チャンネル設計を押さえれば、見やすく・ブランド感も両立した通知が実装できます。

コメント