アプリにメッセージの通知を表示したい。以前のバージョンのAndroidはすべて問題ありませんが、Lollipopでは通知の背景が白です。layout_message_notification.xml
の通知レイアウトにこのXMLコードを使用しました。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/layout_messageNotification"
Android:orientation="horizontal"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@Android:color/transparent">
<LinearLayout
Android:layout_width="0dp"
Android:layout_weight=".2"
Android:layout_height="wrap_content"
Android:background="@Android:color/transparent">
<ImageView
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:scaleType="fitCenter"
Android:src="@drawable/message_icon"/>
</LinearLayout>
<LinearLayout
Android:layout_width="0dp"
Android:layout_weight=".8"
Android:layout_height="wrap_content"
Android:background="@Android:color/transparent">
<TextView
Android:id="@+id/textView_notification_title"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:gravity="right|center_vertical"
Android:layout_margin="15dp"/>
</LinearLayout>
</LinearLayout>
Lollipopでの通知は次のように表示されます。
以前のバージョンのAndroidのように、通知の背景を暗くまたは透明にするにはどうすればよいですか?
この回答は、通知の背景色を変更するhackyメソッドについて説明しています。
注意してください:これは文書化されていない回避策です。これはリフレクションに基づいており、カスタムファームウェアでは壊れている可能性があります。 AndroidLollipopおよびMarshmallowバージョンにのみ適用されます。 Android N以降のバージョンではは機能しません。回避する重大な理由がない限り、デフォルトの色を使用することをお勧めします。
[〜#〜]なぜ[〜#〜]
カスタム通知の背景色を設定する合法的な方法はありません。 Googleは、マテリアルデザインに従って、優先度に応じて通知を白またはライトグレーにする必要があると判断しました。ただし、Googleはこのルールに2つの例外も設けました。
MediaStyle
で作成された通知は、任意の色にすることができます。2番目の例外の結果として、そのような制限は非論理的で不合理に見えます。それが、Googleが推奨する(または強制する)色の代わりにカスタム色を使用したい唯一の言い訳です。
中身BaseStatusBar
を調べて、この制限がどのように課されているかを確認しましょう。通知の背景色が計算される唯一の場所は applyColorsAndBackgroundsメソッド です。if
ステートメントの最初のブランチは、レガシーアプリケーション用です。ここに到達する唯一の方法は、アプリケーションのターゲットSDKをBuild.VERSION_CODES.Lollipop
の下に設定することです。この場合、背景は黒くなります。entry.row.setTintColor
ステートメントに関心があります。それに到達するには、 isMediaNotificationメソッド に含まれているものを含むいくつかのチェックに合格する必要があります。はい、どうぞ:
com.Android.internal.R.id.status_bar_latest_event_content
が必要です。com.Android.internal.R.id.media_actions
を持つウィジェットが含まれている必要があります。[〜#〜]方法[〜#〜]
最も問題となるのは、内部リソースで宣言されており、アプリケーションのレイアウトXMLからアクセスできないIDです。
2番目の問題は、通知で使用されるRemoteViews
がアプリケーション内のレイアウトリソースのIDであり、コードで構築できないことです。その結果、上記のすべてのチェックに合格するために必要なIDを持つレイアウトを追加することはできません。
ただし、Googleは必要に応じてaddView
メソッドとremoveAllViews
メソッドをRemoteViews
に追加し(これらはMediaStyle
通知で使用されます)、非公開にするのを忘れていました。
したがって、最終的なアイデアは単純です。
removeAllViews
ですべてを削除しますaddView
を使用してカスタムレイアウトを追加しますmedia_actions
を含むGoogleによって定義されたレイアウトを追加します(3番目のチェックに合格するため)欠点:
[〜#〜]ソリューション[〜#〜]
カスタムビッグビューには、IDとしてAndroid.R.id.empty
を含むFrameLayout
が含まれている必要があります。実際には、ここでは任意のIDを使用できます。コードで同じIDを参照していることを確認してください(以下を参照)。
// We need theese ids to use internal Android resources
int topId = Resources.getSystem().getIdentifier("status_bar_latest_event_content", "id", "Android");
int topBigLayout = Resources.getSystem().getIdentifier("notification_template_material_big_media_narrow", "layout", "Android");
int topSmallLayout = Resources.getSystem().getIdentifier("notification_template_material_media", "layout", "Android");
RemoteViews viewSmall = ...; // Create our custom view here
RemoteViews viewBig = ...; // Create our custom big view here
// This is invisible inner view - to have media_actions in hierarchy
RemoteViews innerTopView = new RemoteViews("Android", topBigLayout);
viewBig.addView(Android.R.id.empty, innerTopView);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topBigView = new RemoteViews("Android", topBigLayout);
topBigView.removeAllViews(topId);
topBigView.addView(topId, viewBig);
// This should be on top - we need status_bar_latest_event_content as top layout
RemoteViews topSmallView = new RemoteViews("Android", topSmallLayout);
topSmallView.removeAllViews(topId);
topSmallView.addView(topId, viewSmall);
Notification.Builder builder = new Notification.Builder(this);
builder.setSmallIcon(R.drawable.ic_notification)
.setTicker("Some text")
.setColor(0xff000000) // The desired color!
.setContent(topSmallView);
Notification n = builder.build();
n.bigContentView = topBigView;
// Use our notification "n" here as usual
トップレベルのnotification_template_material_big_media_narrow
の代わりに別のレイアウトを使用して、大きなビューの高さを操作することができます。適切なものを検索します ここ notification_template_xxx.xmlファイルの中から。ただし、media_actions
を階層に入れることを忘れないでください。
最終的に、公式のマテリアルデザインに従う場合は 仕様
カスタム通知のテキストには常にスタイルリソースを使用してください
通知のカスタムレイアウトを使用する場合は、デフォルトの背景を上書きせずに、APIバージョンに応じてテキストスタイルを変更することを検討してください。これは、2つのリソーススタイルファイルを作成し、現在のAPIバージョンに従って使用することで実現できます。
values-v21/notify_styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- according to official recommendation custom notifications should has the same text style as default one-->
<style name="NotificationHeader" parent="@Android:style/TextAppearance.Material.Notification.Title" />
<style name="NotificationContent" parent="@Android:style/TextAppearance.Material.Notification.Line2" />
</resources>
そして
values/notify_styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- according to official recommendation custom notifications should has the same text style as default one-->
<style name="NotificationHeader" parent="@Android:style/TextAppearance.StatusBar.EventContent.Title" />
<style name="NotificationContent" parent="@Android:style/TextAppearance.StatusBar.EventContent" />
</resources>
これは、通知の正しい動作です。
この側面を直接制御したい場合は、次のことを行うことをお勧めします。
フォルダーlayout_message_notification.xml
内にres/layout-v21
の代替バージョンを作成します
外側を変更して、この新しいバージョンを少し変更しますレイアウトの背景色:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:id="@+id/layout_messageNotification" Android:orientation="horizontal" Android:layout_width="match_parent" Android:layout_height="match_parent" Android:background="@Android:color/gray"> //...